WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [XEN] Use a separate struct shadow_page_i

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [XEN] Use a separate struct shadow_page_info for shadow pages
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 24 Nov 2006 11:10:13 +0000
Delivery-date: Fri, 24 Nov 2006 03:09:54 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
# Node ID 6f0d8434d23f819e935e85bcee3885ce7bc1abe0
# Parent  a8d2b1393b769048c7b62822e45bef27eef80fb6
[XEN] Use a separate struct shadow_page_info for shadow pages
and move the definitions of shadow types etc out of public headers.
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
---
 xen/arch/x86/mm/shadow/common.c  |  443 ++++++++++++++++-----------------------
 xen/arch/x86/mm/shadow/multi.c   |  258 ++++++++++------------
 xen/arch/x86/mm/shadow/private.h |  155 ++++++++++---
 xen/arch/x86/mm/shadow/types.h   |   24 +-
 xen/include/asm-x86/mm.h         |   42 ---
 xen/include/asm-x86/shadow.h     |   26 --
 6 files changed, 440 insertions(+), 508 deletions(-)

diff -r a8d2b1393b76 -r 6f0d8434d23f xen/arch/x86/mm/shadow/common.c
--- a/xen/arch/x86/mm/shadow/common.c   Tue Nov 21 18:09:23 2006 -0800
+++ b/xen/arch/x86/mm/shadow/common.c   Thu Nov 23 17:40:28 2006 +0000
@@ -190,7 +190,7 @@ struct x86_emulate_ops shadow_emulator_o
  * involves making sure there are no writable mappings available to the guest
  * for this page.
  */
-void shadow_promote(struct vcpu *v, mfn_t gmfn, u32 type)
+void shadow_promote(struct vcpu *v, mfn_t gmfn, unsigned int type)
 {
     struct page_info *page = mfn_to_page(gmfn);
 
@@ -203,8 +203,8 @@ void shadow_promote(struct vcpu *v, mfn_
     if ( !test_and_set_bit(_PGC_page_table, &page->count_info) )
         page->shadow_flags = 0;
 
-    ASSERT(!test_bit(type >> PGC_SH_type_shift, &page->shadow_flags));
-    set_bit(type >> PGC_SH_type_shift, &page->shadow_flags);
+    ASSERT(!test_bit(type, &page->shadow_flags));
+    set_bit(type, &page->shadow_flags);
 }
 
 void shadow_demote(struct vcpu *v, mfn_t gmfn, u32 type)
@@ -212,9 +212,9 @@ void shadow_demote(struct vcpu *v, mfn_t
     struct page_info *page = mfn_to_page(gmfn);
 
     ASSERT(test_bit(_PGC_page_table, &page->count_info));
-    ASSERT(test_bit(type >> PGC_SH_type_shift, &page->shadow_flags));
-
-    clear_bit(type >> PGC_SH_type_shift, &page->shadow_flags);
+    ASSERT(test_bit(type, &page->shadow_flags));
+
+    clear_bit(type, &page->shadow_flags);
 
     if ( (page->shadow_flags & SHF_page_type_mask) == 0 )
     {
@@ -351,75 +351,6 @@ shadow_validate_guest_pt_write(struct vc
 
 /**************************************************************************/
 /* Memory management for shadow pages. */ 
-
-/* Meaning of the count_info field in shadow pages
- * ----------------------------------------------
- * 
- * A count of all references to this page from other shadow pages and
- * guest CR3s (a.k.a. v->arch.shadow.table).  
- *
- * The top bits hold the shadow type and the pinned bit.  Top-level
- * shadows are pinned so that they don't disappear when not in a CR3
- * somewhere.
- *
- * We don't need to use get|put_page for this as the updates are all
- * protected by the shadow lock.  We can't use get|put_page for this
- * as the size of the count on shadow pages is different from that on
- * normal guest pages.
- */
-
-/* Meaning of the type_info field in shadow pages
- * ----------------------------------------------
- * 
- * type_info use depends on the shadow type (from count_info)
- * 
- * PGC_SH_none : This page is in the shadow free pool.  type_info holds
- *                the chunk order for our freelist allocator.
- *
- * PGC_SH_l*_shadow : This page is in use as a shadow. type_info 
- *                     holds the mfn of the guest page being shadowed,
- *
- * PGC_SH_fl1_*_shadow : This page is being used to shatter a superpage.
- *                        type_info holds the gfn being shattered.
- *
- * PGC_SH_monitor_table : This page is part of a monitor table.
- *                         type_info is not used.
- */
-
-/* Meaning of the _domain field in shadow pages
- * --------------------------------------------
- *
- * In shadow pages, this field will always have its least significant bit
- * set.  This ensures that all attempts to get_page() will fail (as all
- * valid pickled domain pointers have a zero for their least significant bit).
- * Instead, the remaining upper bits are used to record the shadow generation
- * counter when the shadow was created.
- */
-
-/* Meaning of the shadow_flags field
- * ----------------------------------
- * 
- * In guest pages that are shadowed, one bit for each kind of shadow they have.
- * 
- * In shadow pages, will be used for holding a representation of the populated
- * entries in this shadow (either a min/max, or a bitmap, or ...)
- *
- * In monitor-table pages, holds the level of the particular page (to save
- * spilling the shadow types into an extra bit by having three types of monitor
- * page).
- */
-
-/* Meaning of the list_head struct in shadow pages
- * -----------------------------------------------
- *
- * In free shadow pages, this is used to hold the free-lists of chunks.
- *
- * In top-level shadow tables, this holds a linked-list of all top-level
- * shadows (used for recovering memory and destroying shadows). 
- *
- * In lower-level shadows, this holds the physical address of a higher-level
- * shadow entry that holds a reference to this shadow (or zero).
- */
 
 /* Allocating shadow pages
  * -----------------------
@@ -475,38 +406,32 @@ unsigned int shadow_min_acceptable_pages
         vcpu_count++;
 
     return (vcpu_count * 128);
-}
-
-/* Using the type_info field to store freelist order */
-#define SH_PFN_ORDER(_p) ((_p)->u.inuse.type_info)
-#define SH_SET_PFN_ORDER(_p, _o)                       \
- do { (_p)->u.inuse.type_info = (_o); } while (0)
- 
+} 
 
 /* Figure out the order of allocation needed for a given shadow type */
 static inline u32
-shadow_order(u32 shadow_type) 
+shadow_order(unsigned int shadow_type) 
 {
 #if CONFIG_PAGING_LEVELS > 2
     static const u32 type_to_order[16] = {
-        0, /* PGC_SH_none           */
-        1, /* PGC_SH_l1_32_shadow   */
-        1, /* PGC_SH_fl1_32_shadow  */
-        2, /* PGC_SH_l2_32_shadow   */
-        0, /* PGC_SH_l1_pae_shadow  */
-        0, /* PGC_SH_fl1_pae_shadow */
-        0, /* PGC_SH_l2_pae_shadow  */
-        0, /* PGC_SH_l2h_pae_shadow */
-        0, /* PGC_SH_l1_64_shadow   */
-        0, /* PGC_SH_fl1_64_shadow  */
-        0, /* PGC_SH_l2_64_shadow   */
-        0, /* PGC_SH_l3_64_shadow   */
-        0, /* PGC_SH_l4_64_shadow   */
-        2, /* PGC_SH_p2m_table      */
-        0  /* PGC_SH_monitor_table  */
+        0, /* SH_type_none           */
+        1, /* SH_type_l1_32_shadow   */
+        1, /* SH_type_fl1_32_shadow  */
+        2, /* SH_type_l2_32_shadow   */
+        0, /* SH_type_l1_pae_shadow  */
+        0, /* SH_type_fl1_pae_shadow */
+        0, /* SH_type_l2_pae_shadow  */
+        0, /* SH_type_l2h_pae_shadow */
+        0, /* SH_type_l1_64_shadow   */
+        0, /* SH_type_fl1_64_shadow  */
+        0, /* SH_type_l2_64_shadow   */
+        0, /* SH_type_l3_64_shadow   */
+        0, /* SH_type_l4_64_shadow   */
+        2, /* SH_type_p2m_table      */
+        0  /* SH_type_monitor_table  */
         };
-    u32 type = (shadow_type & PGC_SH_type_mask) >> PGC_SH_type_shift;
-    return type_to_order[type];
+    ASSERT(shadow_type < 16);
+    return type_to_order[shadow_type];
 #else  /* 32-bit Xen only ever shadows 32-bit guests on 32-bit shadows. */
     return 0;
 #endif
@@ -528,10 +453,10 @@ static inline int chunk_is_available(str
  * non-Xen mappings in this top-level shadow mfn */
 void shadow_unhook_mappings(struct vcpu *v, mfn_t smfn)
 {
-    struct page_info *pg = mfn_to_page(smfn);
-    switch ( (pg->count_info & PGC_SH_type_mask) >> PGC_SH_type_shift )
-    {
-    case PGC_SH_l2_32_shadow >> PGC_SH_type_shift:
+    struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
+    switch ( sp->type )
+    {
+    case SH_type_l2_32_shadow:
 #if CONFIG_PAGING_LEVELS == 2
         SHADOW_INTERNAL_NAME(sh_unhook_32b_mappings,2,2)(v,smfn);
 #else
@@ -539,20 +464,18 @@ void shadow_unhook_mappings(struct vcpu 
 #endif
         break;
 #if CONFIG_PAGING_LEVELS >= 3
-    case PGC_SH_l2_pae_shadow >> PGC_SH_type_shift:
-    case PGC_SH_l2h_pae_shadow >> PGC_SH_type_shift:
+    case SH_type_l2_pae_shadow:
+    case SH_type_l2h_pae_shadow:
         SHADOW_INTERNAL_NAME(sh_unhook_pae_mappings,3,3)(v,smfn);
         break;
 #endif
 #if CONFIG_PAGING_LEVELS >= 4
-    case PGC_SH_l4_64_shadow >> PGC_SH_type_shift:
+    case SH_type_l4_64_shadow:
         SHADOW_INTERNAL_NAME(sh_unhook_64b_mappings,4,4)(v,smfn);
         break;
 #endif
     default:
-        SHADOW_PRINTK("top-level shadow has bad type %08lx\n", 
-                       (unsigned long)((pg->count_info & PGC_SH_type_mask)
-                                       >> PGC_SH_type_shift));
+        SHADOW_PRINTK("top-level shadow has bad type %08x\n", sp->type);
         BUG();
     }
 }
@@ -569,7 +492,7 @@ void shadow_prealloc(struct domain *d, u
      * per-vcpu shadows, any will do */
     struct vcpu *v, *v2;
     struct list_head *l, *t;
-    struct page_info *pg;
+    struct shadow_page_info *sp;
     cpumask_t flushmask = CPU_MASK_NONE;
     mfn_t smfn;
 
@@ -584,8 +507,8 @@ void shadow_prealloc(struct domain *d, u
     perfc_incrc(shadow_prealloc_1);
     list_for_each_backwards_safe(l, t, &d->arch.shadow.toplevel_shadows)
     {
-        pg = list_entry(l, struct page_info, list);
-        smfn = page_to_mfn(pg);
+        sp = list_entry(l, struct shadow_page_info, list);
+        smfn = shadow_page_to_mfn(sp);
 
         /* Unpin this top-level shadow */
         sh_unpin(v, smfn);
@@ -600,8 +523,8 @@ void shadow_prealloc(struct domain *d, u
     perfc_incrc(shadow_prealloc_2);
     list_for_each_backwards_safe(l, t, &d->arch.shadow.toplevel_shadows)
     {
-        pg = list_entry(l, struct page_info, list);
-        smfn = page_to_mfn(pg);
+        sp = list_entry(l, struct shadow_page_info, list);
+        smfn = shadow_page_to_mfn(sp);
         shadow_unhook_mappings(v, smfn);
 
         /* Remember to flush TLBs: we have removed shadow entries that 
@@ -642,7 +565,7 @@ static void shadow_blow_tables(unsigned 
 static void shadow_blow_tables(unsigned char c)
 {
     struct list_head *l, *t;
-    struct page_info *pg;
+    struct shadow_page_info *sp;
     struct domain *d;
     struct vcpu *v;
     mfn_t smfn;
@@ -657,16 +580,16 @@ static void shadow_blow_tables(unsigned 
             /* Pass one: unpin all top-level pages */
             list_for_each_backwards_safe(l,t, &d->arch.shadow.toplevel_shadows)
             {
-                pg = list_entry(l, struct page_info, list);
-                smfn = page_to_mfn(pg);
+                sp = list_entry(l, struct shadow_page_info, list);
+                smfn = shadow_page_to_mfn(sp);
                 sh_unpin(v, smfn);
             }
 
             /* Second pass: unhook entries of in-use shadows */
             list_for_each_backwards_safe(l,t, &d->arch.shadow.toplevel_shadows)
             {
-                pg = list_entry(l, struct page_info, list);
-                smfn = page_to_mfn(pg);
+                sp = list_entry(l, struct shadow_page_info, list);
+                smfn = shadow_page_to_mfn(sp);
                 shadow_unhook_mappings(v, smfn);
             }
             
@@ -693,7 +616,7 @@ mfn_t shadow_alloc(struct domain *d,
                     u32 shadow_type,
                     unsigned long backpointer)
 {
-    struct page_info *pg = NULL;
+    struct shadow_page_info *sp = NULL;
     unsigned int order = shadow_order(shadow_type);
     cpumask_t mask;
     void *p;
@@ -701,51 +624,54 @@ mfn_t shadow_alloc(struct domain *d,
 
     ASSERT(shadow_lock_is_acquired(d));
     ASSERT(order <= SHADOW_MAX_ORDER);
-    ASSERT(shadow_type != PGC_SH_none);
+    ASSERT(shadow_type != SH_type_none);
     perfc_incrc(shadow_alloc);
 
     /* Find smallest order which can satisfy the request. */
     for ( i = order; i <= SHADOW_MAX_ORDER; i++ )
         if ( !list_empty(&d->arch.shadow.freelists[i]) )
         {
-            pg = list_entry(d->arch.shadow.freelists[i].next, 
-                            struct page_info, list);
-            list_del(&pg->list);
+            sp = list_entry(d->arch.shadow.freelists[i].next, 
+                            struct shadow_page_info, list);
+            list_del(&sp->list);
             
             /* We may have to halve the chunk a number of times. */
             while ( i != order )
             {
                 i--;
-                SH_SET_PFN_ORDER(pg, i);
-                list_add_tail(&pg->list, &d->arch.shadow.freelists[i]);
-                pg += 1 << i;
+                sp->order = i;
+                list_add_tail(&sp->list, &d->arch.shadow.freelists[i]);
+                sp += 1 << i;
             }
             d->arch.shadow.free_pages -= 1 << order;
 
             /* Init page info fields and clear the pages */
             for ( i = 0; i < 1<<order ; i++ ) 
             {
-                pg[i].u.inuse.type_info = backpointer;
-                pg[i].count_info = shadow_type;
-                pg[i].shadow_flags = 0;
-                INIT_LIST_HEAD(&pg[i].list);
                 /* Before we overwrite the old contents of this page, 
                  * we need to be sure that no TLB holds a pointer to it. */
                 mask = d->domain_dirty_cpumask;
-                tlbflush_filter(mask, pg[i].tlbflush_timestamp);
+                tlbflush_filter(mask, sp[i].tlbflush_timestamp);
                 if ( unlikely(!cpus_empty(mask)) )
                 {
                     perfc_incrc(shadow_alloc_tlbflush);
                     flush_tlb_mask(mask);
                 }
                 /* Now safe to clear the page for reuse */
-                p = sh_map_domain_page(page_to_mfn(pg+i));
+                p = sh_map_domain_page(shadow_page_to_mfn(sp+i));
                 ASSERT(p != NULL);
                 clear_page(p);
                 sh_unmap_domain_page(p);
+                INIT_LIST_HEAD(&sp[i].list);
+                sp[i].type = shadow_type;
+                sp[i].pinned = 0;
+                sp[i].logdirty = 0;
+                sp[i].count = 0;
+                sp[i].backpointer = backpointer;
+                sp[i].next_shadow = NULL;
                 perfc_incr(shadow_alloc_count);
             }
-            return page_to_mfn(pg);
+            return shadow_page_to_mfn(sp);
         }
     
     /* If we get here, we failed to allocate. This should never happen.
@@ -760,7 +686,7 @@ mfn_t shadow_alloc(struct domain *d,
 /* Return some shadow pages to the pool. */
 void shadow_free(struct domain *d, mfn_t smfn)
 {
-    struct page_info *pg = mfn_to_page(smfn); 
+    struct shadow_page_info *sp = mfn_to_shadow_page(smfn); 
     u32 shadow_type;
     unsigned long order;
     unsigned long mask;
@@ -769,9 +695,9 @@ void shadow_free(struct domain *d, mfn_t
     ASSERT(shadow_lock_is_acquired(d));
     perfc_incrc(shadow_free);
 
-    shadow_type = pg->count_info & PGC_SH_type_mask;
-    ASSERT(shadow_type != PGC_SH_none);
-    ASSERT(shadow_type != PGC_SH_p2m_table);
+    shadow_type = sp->type;
+    ASSERT(shadow_type != SH_type_none);
+    ASSERT(shadow_type != SH_type_p2m_table);
     order = shadow_order(shadow_type);
 
     d->arch.shadow.free_pages += 1 << order;
@@ -788,12 +714,12 @@ void shadow_free(struct domain *d, mfn_t
         }
 #endif
         /* Strip out the type: this is now a free shadow page */
-        pg[i].count_info = 0;
+        sp[i].type = 0;
         /* Remember the TLB timestamp so we will know whether to flush 
          * TLBs when we reuse the page.  Because the destructors leave the
          * contents of the pages in place, we can delay TLB flushes until
          * just before the allocator hands the page out again. */
-        pg[i].tlbflush_timestamp = tlbflush_current_time();
+        sp[i].tlbflush_timestamp = tlbflush_current_time();
         perfc_decr(shadow_alloc_count);
     }
 
@@ -801,25 +727,23 @@ void shadow_free(struct domain *d, mfn_t
     while ( order < SHADOW_MAX_ORDER )
     {
         mask = 1 << order;
-        if ( (mfn_x(page_to_mfn(pg)) & mask) ) {
+        if ( (mfn_x(shadow_page_to_mfn(sp)) & mask) ) {
             /* Merge with predecessor block? */
-            if ( (((pg-mask)->count_info & PGC_SH_type_mask) != PGT_none) 
-                 || (SH_PFN_ORDER(pg-mask) != order) )
+            if ( ((sp-mask)->type != PGT_none) || ((sp-mask)->order != order) )
                 break;
-            list_del(&(pg-mask)->list);
-            pg -= mask;
+            list_del(&(sp-mask)->list);
+            sp -= mask;
         } else {
             /* Merge with successor block? */
-            if ( (((pg+mask)->count_info & PGC_SH_type_mask) != PGT_none)
-                 || (SH_PFN_ORDER(pg+mask) != order) )
+            if ( ((sp+mask)->type != PGT_none) || ((sp+mask)->order != order) )
                 break;
-            list_del(&(pg+mask)->list);
+            list_del(&(sp+mask)->list);
         }
         order++;
     }
 
-    SH_SET_PFN_ORDER(pg, order);
-    list_add_tail(&pg->list, &d->arch.shadow.freelists[order]);
+    sp->order = order;
+    list_add_tail(&sp->list, &d->arch.shadow.freelists[order]);
 }
 
 /* Divert some memory from the pool to be used by the p2m mapping.
@@ -843,7 +767,7 @@ shadow_alloc_p2m_pages(struct domain *d)
          < (shadow_min_acceptable_pages(d) + (1<<SHADOW_MAX_ORDER)) )
         return 0; /* Not enough shadow memory: need to increase it first */
     
-    pg = mfn_to_page(shadow_alloc(d, PGC_SH_p2m_table, 0));
+    pg = mfn_to_page(shadow_alloc(d, SH_type_p2m_table, 0));
     d->arch.shadow.p2m_pages += (1<<SHADOW_MAX_ORDER);
     d->arch.shadow.total_pages -= (1<<SHADOW_MAX_ORDER);
     for (i = 0; i < (1<<SHADOW_MAX_ORDER); i++)
@@ -1221,7 +1145,7 @@ static void shadow_p2m_teardown(struct d
         pg = list_entry(entry, struct page_info, list);
         list_del(entry);
         /* Should have just the one ref we gave it in alloc_p2m_page() */
-        if ( (pg->count_info & PGC_SH_count_mask) != 1 )
+        if ( (pg->count_info & PGC_count_mask) != 1 )
         {
             SHADOW_PRINTK("Odd p2m page count c=%#x t=%"PRtype_info"\n",
                            pg->count_info, pg->u.inuse.type_info);
@@ -1256,7 +1180,7 @@ static unsigned int set_sh_allocation(st
                                        unsigned int pages,
                                        int *preempted)
 {
-    struct page_info *pg;
+    struct shadow_page_info *sp;
     unsigned int lower_bound;
     int j;
 
@@ -1278,8 +1202,9 @@ static unsigned int set_sh_allocation(st
         if ( d->arch.shadow.total_pages < pages ) 
         {
             /* Need to allocate more memory from domheap */
-            pg = alloc_domheap_pages(NULL, SHADOW_MAX_ORDER, 0); 
-            if ( pg == NULL ) 
+            sp = (struct shadow_page_info *)
+                alloc_domheap_pages(NULL, SHADOW_MAX_ORDER, 0); 
+            if ( sp == NULL ) 
             { 
                 SHADOW_PRINTK("failed to allocate shadow pages.\n");
                 return -ENOMEM;
@@ -1288,11 +1213,15 @@ static unsigned int set_sh_allocation(st
             d->arch.shadow.total_pages += 1<<SHADOW_MAX_ORDER;
             for ( j = 0; j < 1<<SHADOW_MAX_ORDER; j++ ) 
             {
-                pg[j].u.inuse.type_info = 0;  /* Free page */
-                pg[j].tlbflush_timestamp = 0; /* Not in any TLB */
+                sp[j].type = 0;  
+                sp[j].pinned = 0;
+                sp[j].logdirty = 0;
+                sp[j].count = 0;
+                sp[j].mbz = 0;
+                sp[j].tlbflush_timestamp = 0; /* Not in any TLB */
             }
-            SH_SET_PFN_ORDER(pg, SHADOW_MAX_ORDER);
-            list_add_tail(&pg->list, 
+            sp->order = SHADOW_MAX_ORDER;
+            list_add_tail(&sp->list, 
                           &d->arch.shadow.freelists[SHADOW_MAX_ORDER]);
         } 
         else if ( d->arch.shadow.total_pages > pages ) 
@@ -1300,12 +1229,12 @@ static unsigned int set_sh_allocation(st
             /* Need to return memory to domheap */
             shadow_prealloc(d, SHADOW_MAX_ORDER);
             ASSERT(!list_empty(&d->arch.shadow.freelists[SHADOW_MAX_ORDER]));
-            pg = list_entry(d->arch.shadow.freelists[SHADOW_MAX_ORDER].next, 
-                            struct page_info, list);
-            list_del(&pg->list);
+            sp = list_entry(d->arch.shadow.freelists[SHADOW_MAX_ORDER].next, 
+                            struct shadow_page_info, list);
+            list_del(&sp->list);
             d->arch.shadow.free_pages -= 1<<SHADOW_MAX_ORDER;
             d->arch.shadow.total_pages -= 1<<SHADOW_MAX_ORDER;
-            free_domheap_pages(pg, SHADOW_MAX_ORDER);
+            free_domheap_pages((struct page_info *)sp, SHADOW_MAX_ORDER);
         }
 
         /* Check to see if we need to yield and try again */
@@ -1357,7 +1286,7 @@ static void sh_hash_audit_bucket(struct 
 /* Audit one bucket of the hash table */
 {
     struct shadow_hash_entry *e, *x;
-    struct page_info *pg;
+    struct shadow_page_info *sp;
 
     if ( !(SHADOW_AUDIT_ENABLE) )
         return;
@@ -1369,7 +1298,7 @@ static void sh_hash_audit_bucket(struct 
         /* Empty link? */
         BUG_ON( e->t == 0 ); 
         /* Bogus type? */
-        BUG_ON( e->t > (PGC_SH_max_shadow >> PGC_SH_type_shift) );
+        BUG_ON( e->t > SH_type_max_shadow );
         /* Wrong bucket? */
         BUG_ON( sh_hash(e->n, e->t) % SHADOW_HASH_BUCKETS != bucket ); 
         /* Duplicate entry? */
@@ -1377,17 +1306,16 @@ static void sh_hash_audit_bucket(struct 
             BUG_ON( x->n == e->n && x->t == e->t );
         /* Bogus MFN? */
         BUG_ON( !valid_mfn(e->smfn) );
-        pg = mfn_to_page(e->smfn);
+        sp = mfn_to_shadow_page(e->smfn);
         /* Not a shadow? */
-        BUG_ON( page_get_owner(pg) != 0 );
+        BUG_ON( sp->mbz != 0 );
         /* Wrong kind of shadow? */
-        BUG_ON( (pg->count_info & PGC_SH_type_mask) >> PGC_SH_type_shift 
-                != e->t ); 
+        BUG_ON( sp->type != e->t ); 
         /* Bad backlink? */
-        BUG_ON( pg->u.inuse.type_info != e->n );
-        if ( e->t != (PGC_SH_fl1_32_shadow >> PGC_SH_type_shift)
-             && e->t != (PGC_SH_fl1_pae_shadow >> PGC_SH_type_shift)
-             && e->t != (PGC_SH_fl1_64_shadow >> PGC_SH_type_shift) )
+        BUG_ON( sp->backpointer != e->n );
+        if ( e->t != SH_type_fl1_32_shadow
+             && e->t != SH_type_fl1_pae_shadow
+             && e->t != SH_type_fl1_64_shadow )
         {
             struct page_info *gpg = mfn_to_page(_mfn(e->n));
             /* Bad shadow flags on guest page? */
@@ -1752,66 +1680,66 @@ static void hash_foreach(struct vcpu *v,
 
 void sh_destroy_shadow(struct vcpu *v, mfn_t smfn)
 {
-    struct page_info *pg = mfn_to_page(smfn);
-    u32 t = pg->count_info & PGC_SH_type_mask;
+    struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
+    unsigned int t = sp->type;
 
 
     SHADOW_PRINTK("smfn=%#lx\n", mfn_x(smfn));
 
     /* Double-check, if we can, that the shadowed page belongs to this
      * domain, (by following the back-pointer). */
-    ASSERT(t == PGC_SH_fl1_32_shadow  ||  
-           t == PGC_SH_fl1_pae_shadow ||  
-           t == PGC_SH_fl1_64_shadow  || 
-           t == PGC_SH_monitor_table  || 
-           (page_get_owner(mfn_to_page(_mfn(pg->u.inuse.type_info))) 
+    ASSERT(t == SH_type_fl1_32_shadow  ||  
+           t == SH_type_fl1_pae_shadow ||  
+           t == SH_type_fl1_64_shadow  || 
+           t == SH_type_monitor_table  || 
+           (page_get_owner(mfn_to_page(_mfn(sp->backpointer))) 
             == v->domain)); 
 
     /* The down-shifts here are so that the switch statement is on nice
      * small numbers that the compiler will enjoy */
-    switch ( t >> PGC_SH_type_shift )
+    switch ( t )
     {
 #if CONFIG_PAGING_LEVELS == 2
-    case PGC_SH_l1_32_shadow >> PGC_SH_type_shift:
-    case PGC_SH_fl1_32_shadow >> PGC_SH_type_shift:
+    case SH_type_l1_32_shadow:
+    case SH_type_fl1_32_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l1_shadow, 2, 2)(v, smfn); 
         break;
-    case PGC_SH_l2_32_shadow >> PGC_SH_type_shift:
+    case SH_type_l2_32_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l2_shadow, 2, 2)(v, smfn);
         break;
 #else /* PAE or 64bit */
-    case PGC_SH_l1_32_shadow >> PGC_SH_type_shift:
-    case PGC_SH_fl1_32_shadow >> PGC_SH_type_shift:
+    case SH_type_l1_32_shadow:
+    case SH_type_fl1_32_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l1_shadow, 3, 2)(v, smfn);
         break;
-    case PGC_SH_l2_32_shadow >> PGC_SH_type_shift:
+    case SH_type_l2_32_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l2_shadow, 3, 2)(v, smfn);
         break;
 #endif
 
 #if CONFIG_PAGING_LEVELS >= 3
-    case PGC_SH_l1_pae_shadow >> PGC_SH_type_shift:
-    case PGC_SH_fl1_pae_shadow >> PGC_SH_type_shift:
+    case SH_type_l1_pae_shadow:
+    case SH_type_fl1_pae_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l1_shadow, 3, 3)(v, smfn);
         break;
-    case PGC_SH_l2_pae_shadow >> PGC_SH_type_shift:
-    case PGC_SH_l2h_pae_shadow >> PGC_SH_type_shift:
+    case SH_type_l2_pae_shadow:
+    case SH_type_l2h_pae_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l2_shadow, 3, 3)(v, smfn);
         break;
 #endif
 
 #if CONFIG_PAGING_LEVELS >= 4
-    case PGC_SH_l1_64_shadow >> PGC_SH_type_shift:
-    case PGC_SH_fl1_64_shadow >> PGC_SH_type_shift:
+    case SH_type_l1_64_shadow:
+    case SH_type_fl1_64_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l1_shadow, 4, 4)(v, smfn);
         break;
-    case PGC_SH_l2_64_shadow >> PGC_SH_type_shift:
+    case SH_type_l2_64_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l2_shadow, 4, 4)(v, smfn);
         break;
-    case PGC_SH_l3_64_shadow >> PGC_SH_type_shift:
+    case SH_type_l3_64_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l3_shadow, 4, 4)(v, smfn);
         break;
-    case PGC_SH_l4_64_shadow >> PGC_SH_type_shift:
+    case SH_type_l4_64_shadow:
         SHADOW_INTERNAL_NAME(sh_destroy_l4_shadow, 4, 4)(v, smfn);
         break;
 #endif
@@ -1867,12 +1795,12 @@ int shadow_remove_write_access(struct vc
     };
 
     static unsigned int callback_mask = 
-          1 << (PGC_SH_l1_32_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_fl1_32_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_l1_pae_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_fl1_pae_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_l1_64_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_fl1_64_shadow >> PGC_SH_type_shift)
+          1 << SH_type_l1_32_shadow
+        | 1 << SH_type_fl1_32_shadow
+        | 1 << SH_type_l1_pae_shadow
+        | 1 << SH_type_fl1_pae_shadow
+        | 1 << SH_type_l1_64_shadow
+        | 1 << SH_type_fl1_64_shadow
         ;
     struct page_info *pg = mfn_to_page(gmfn);
 
@@ -1979,8 +1907,7 @@ int shadow_remove_write_access(struct vc
     {
         unsigned long old_count = (pg->u.inuse.type_info & PGT_count_mask);
         mfn_t last_smfn = _mfn(v->arch.shadow.last_writeable_pte_smfn);
-        int shtype = (mfn_to_page(last_smfn)->count_info & PGC_SH_type_mask) 
-            >> PGC_SH_type_shift;
+        int shtype = mfn_to_shadow_page(last_smfn)->type;
 
         if ( callbacks[shtype] ) 
             callbacks[shtype](v, last_smfn, gmfn);
@@ -2057,12 +1984,12 @@ int shadow_remove_all_mappings(struct vc
     };
 
     static unsigned int callback_mask = 
-          1 << (PGC_SH_l1_32_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_fl1_32_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_l1_pae_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_fl1_pae_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_l1_64_shadow >> PGC_SH_type_shift)
-        | 1 << (PGC_SH_fl1_64_shadow >> PGC_SH_type_shift)
+          1 << SH_type_l1_32_shadow
+        | 1 << SH_type_fl1_32_shadow
+        | 1 << SH_type_l1_pae_shadow
+        | 1 << SH_type_fl1_pae_shadow
+        | 1 << SH_type_l1_64_shadow
+        | 1 << SH_type_fl1_64_shadow
         ;
 
     perfc_incrc(shadow_mappings);
@@ -2106,34 +2033,34 @@ static int sh_remove_shadow_via_pointer(
 /* Follow this shadow's up-pointer, if it has one, and remove the reference
  * found there.  Returns 1 if that was the only reference to this shadow */
 {
-    struct page_info *pg = mfn_to_page(smfn);
+    struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
     mfn_t pmfn;
     void *vaddr;
     int rc;
 
-    ASSERT((pg->count_info & PGC_SH_type_mask) > 0);
-    ASSERT((pg->count_info & PGC_SH_type_mask) < PGC_SH_max_shadow);
-    ASSERT((pg->count_info & PGC_SH_type_mask) != PGC_SH_l2_32_shadow);
-    ASSERT((pg->count_info & PGC_SH_type_mask) != PGC_SH_l2_pae_shadow);
-    ASSERT((pg->count_info & PGC_SH_type_mask) != PGC_SH_l2h_pae_shadow);
-    ASSERT((pg->count_info & PGC_SH_type_mask) != PGC_SH_l4_64_shadow);
+    ASSERT(sp->type > 0);
+    ASSERT(sp->type < SH_type_max_shadow);
+    ASSERT(sp->type != SH_type_l2_32_shadow);
+    ASSERT(sp->type != SH_type_l2_pae_shadow);
+    ASSERT(sp->type != SH_type_l2h_pae_shadow);
+    ASSERT(sp->type != SH_type_l4_64_shadow);
     
-    if (pg->up == 0) return 0;
-    pmfn = _mfn(pg->up >> PAGE_SHIFT);
+    if (sp->up == 0) return 0;
+    pmfn = _mfn(sp->up >> PAGE_SHIFT);
     ASSERT(valid_mfn(pmfn));
     vaddr = sh_map_domain_page(pmfn);
     ASSERT(vaddr);
-    vaddr += pg->up & (PAGE_SIZE-1);
+    vaddr += sp->up & (PAGE_SIZE-1);
     ASSERT(l1e_get_pfn(*(l1_pgentry_t *)vaddr) == mfn_x(smfn));
     
     /* Is this the only reference to this shadow? */
-    rc = ((pg->count_info & PGC_SH_count_mask) == 1) ? 1 : 0;
+    rc = (sp->count == 1) ? 1 : 0;
 
     /* Blank the offending entry */
-    switch ((pg->count_info & PGC_SH_type_mask)) 
-    {
-    case PGC_SH_l1_32_shadow:
-    case PGC_SH_l2_32_shadow:
+    switch (sp->type) 
+    {
+    case SH_type_l1_32_shadow:
+    case SH_type_l2_32_shadow:
 #if CONFIG_PAGING_LEVELS == 2
         SHADOW_INTERNAL_NAME(sh_clear_shadow_entry,2,2)(v, vaddr, pmfn);
 #else
@@ -2141,16 +2068,16 @@ static int sh_remove_shadow_via_pointer(
 #endif
         break;
 #if CONFIG_PAGING_LEVELS >=3
-    case PGC_SH_l1_pae_shadow:
-    case PGC_SH_l2_pae_shadow:
-    case PGC_SH_l2h_pae_shadow:
+    case SH_type_l1_pae_shadow:
+    case SH_type_l2_pae_shadow:
+    case SH_type_l2h_pae_shadow:
         SHADOW_INTERNAL_NAME(sh_clear_shadow_entry,3,3)(v, vaddr, pmfn);
         break;
 #if CONFIG_PAGING_LEVELS >= 4
-    case PGC_SH_l1_64_shadow:
-    case PGC_SH_l2_64_shadow:
-    case PGC_SH_l3_64_shadow:
-    case PGC_SH_l4_64_shadow:
+    case SH_type_l1_64_shadow:
+    case SH_type_l2_64_shadow:
+    case SH_type_l3_64_shadow:
+    case SH_type_l4_64_shadow:
         SHADOW_INTERNAL_NAME(sh_clear_shadow_entry,4,4)(v, vaddr, pmfn);
         break;
 #endif
@@ -2219,18 +2146,18 @@ void sh_remove_shadows(struct vcpu *v, m
     /* Another lookup table, for choosing which mask to use */
     static unsigned int masks[16] = {
         0, /* none    */
-        1 << (PGC_SH_l2_32_shadow >> PGC_SH_type_shift), /* l1_32   */
+        1 << SH_type_l2_32_shadow, /* l1_32   */
         0, /* fl1_32  */
         0, /* l2_32   */
-        ((1 << (PGC_SH_l2h_pae_shadow >> PGC_SH_type_shift))
-         | (1 << (PGC_SH_l2_pae_shadow >> PGC_SH_type_shift))), /* l1_pae  */
+        ((1 << SH_type_l2h_pae_shadow)
+         | (1 << SH_type_l2_pae_shadow)), /* l1_pae  */
         0, /* fl1_pae */
         0, /* l2_pae  */
         0, /* l2h_pae  */
-        1 << (PGC_SH_l2_64_shadow >> PGC_SH_type_shift), /* l1_64   */
+        1 << SH_type_l2_64_shadow, /* l1_64   */
         0, /* fl1_64  */
-        1 << (PGC_SH_l3_64_shadow >> PGC_SH_type_shift), /* l2_64   */
-        1 << (PGC_SH_l4_64_shadow >> PGC_SH_type_shift), /* l3_64   */
+        1 << SH_type_l3_64_shadow, /* l2_64   */
+        1 << SH_type_l4_64_shadow, /* l3_64   */
         0, /* l4_64   */
         0, /* p2m     */
         0  /* unused  */
@@ -2257,31 +2184,31 @@ void sh_remove_shadows(struct vcpu *v, m
      * call will remove at most one shadow, and terminate immediately when
      * it does remove it, so we never walk the hash after doing a deletion.  */
 #define DO_UNSHADOW(_type) do {                                 \
-    t = (_type) >> PGC_SH_type_shift;                           \
+    t = (_type);                                                \
     smfn = shadow_hash_lookup(v, mfn_x(gmfn), t);               \
     if ( !sh_remove_shadow_via_pointer(v, smfn) && !fast )      \
         hash_foreach(v, masks[t], callbacks, smfn);             \
 } while (0)
 
     /* Top-level shadows need to be unpinned */
-#define DO_UNPIN(_type) do {                                            \
-    t = (_type) >> PGC_SH_type_shift;                                   \
-    smfn = shadow_hash_lookup(v, mfn_x(gmfn), t);                       \
-    if ( mfn_to_page(smfn)->count_info & PGC_SH_pinned )                \
-        sh_unpin(v, smfn);                                              \
+#define DO_UNPIN(_type) do {                            \
+    t = (_type);                                        \
+    smfn = shadow_hash_lookup(v, mfn_x(gmfn), t);       \
+    if ( mfn_to_shadow_page(smfn)->pinned )             \
+        sh_unpin(v, smfn);                              \
 } while (0)
 
-    if ( sh_flags & SHF_L1_32 )   DO_UNSHADOW(PGC_SH_l1_32_shadow);
-    if ( sh_flags & SHF_L2_32 )   DO_UNPIN(PGC_SH_l2_32_shadow);
+    if ( sh_flags & SHF_L1_32 )   DO_UNSHADOW(SH_type_l1_32_shadow);
+    if ( sh_flags & SHF_L2_32 )   DO_UNPIN(SH_type_l2_32_shadow);
 #if CONFIG_PAGING_LEVELS >= 3
-    if ( sh_flags & SHF_L1_PAE )  DO_UNSHADOW(PGC_SH_l1_pae_shadow);
-    if ( sh_flags & SHF_L2_PAE )  DO_UNPIN(PGC_SH_l2_pae_shadow);
-    if ( sh_flags & SHF_L2H_PAE ) DO_UNPIN(PGC_SH_l2h_pae_shadow);
+    if ( sh_flags & SHF_L1_PAE )  DO_UNSHADOW(SH_type_l1_pae_shadow);
+    if ( sh_flags & SHF_L2_PAE )  DO_UNPIN(SH_type_l2_pae_shadow);
+    if ( sh_flags & SHF_L2H_PAE ) DO_UNPIN(SH_type_l2h_pae_shadow);
 #if CONFIG_PAGING_LEVELS >= 4
-    if ( sh_flags & SHF_L1_64 )   DO_UNSHADOW(PGC_SH_l1_64_shadow);
-    if ( sh_flags & SHF_L2_64 )   DO_UNSHADOW(PGC_SH_l2_64_shadow);
-    if ( sh_flags & SHF_L3_64 )   DO_UNSHADOW(PGC_SH_l3_64_shadow);
-    if ( sh_flags & SHF_L4_64 )   DO_UNPIN(PGC_SH_l4_64_shadow);
+    if ( sh_flags & SHF_L1_64 )   DO_UNSHADOW(SH_type_l1_64_shadow);
+    if ( sh_flags & SHF_L2_64 )   DO_UNSHADOW(SH_type_l2_64_shadow);
+    if ( sh_flags & SHF_L3_64 )   DO_UNSHADOW(SH_type_l3_64_shadow);
+    if ( sh_flags & SHF_L4_64 )   DO_UNPIN(SH_type_l4_64_shadow);
 #endif
 #endif
 
@@ -2292,7 +2219,7 @@ void sh_remove_shadows(struct vcpu *v, m
     if ( !fast && (pg->count_info & PGC_page_table) )
     {
         SHADOW_ERROR("can't find all shadows of mfn %05lx "
-                     "(shadow_flags=%08x)\n",
+                     "(shadow_flags=%08lx)\n",
                       mfn_x(gmfn), pg->shadow_flags);
         if ( all ) 
             domain_crash(v->domain);
@@ -3021,16 +2948,16 @@ static int shadow_log_dirty_op(
     if ( clean ) 
     {
         struct list_head *l, *t;
-        struct page_info *pg;
+        struct shadow_page_info *sp;
 
         /* Need to revoke write access to the domain's pages again. 
          * In future, we'll have a less heavy-handed approach to this, 
          * but for now, we just unshadow everything except Xen. */
         list_for_each_safe(l, t, &d->arch.shadow.toplevel_shadows)
         {
-            pg = list_entry(l, struct page_info, list);
+            sp = list_entry(l, struct shadow_page_info, list);
             if ( d->vcpu[0] != NULL )
-                shadow_unhook_mappings(d->vcpu[0], page_to_mfn(pg));
+                shadow_unhook_mappings(d->vcpu[0], shadow_page_to_mfn(sp));
         }
 
         d->arch.shadow.fault_count = 0;
diff -r a8d2b1393b76 -r 6f0d8434d23f xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c    Tue Nov 21 18:09:23 2006 -0800
+++ b/xen/arch/x86/mm/shadow/multi.c    Thu Nov 23 17:40:28 2006 +0000
@@ -100,13 +100,12 @@ get_fl1_shadow_status(struct vcpu *v, gf
 get_fl1_shadow_status(struct vcpu *v, gfn_t gfn)
 /* Look for FL1 shadows in the hash table */
 {
-    mfn_t smfn = shadow_hash_lookup(v, gfn_x(gfn),
-                                     PGC_SH_fl1_shadow >> PGC_SH_type_shift);
+    mfn_t smfn = shadow_hash_lookup(v, gfn_x(gfn), SH_type_fl1_shadow);
 
     if ( unlikely(shadow_mode_log_dirty(v->domain) && valid_mfn(smfn)) )
     {
-        struct page_info *page = mfn_to_page(smfn);
-        if ( !(page->count_info & PGC_SH_log_dirty) )
+        struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
+        if ( !(sp->logdirty) )
             shadow_convert_to_log_dirty(v, smfn);
     }
 
@@ -117,14 +116,13 @@ get_shadow_status(struct vcpu *v, mfn_t 
 get_shadow_status(struct vcpu *v, mfn_t gmfn, u32 shadow_type)
 /* Look for shadows in the hash table */
 {
-    mfn_t smfn = shadow_hash_lookup(v, mfn_x(gmfn),
-                                     shadow_type >> PGC_SH_type_shift);
+    mfn_t smfn = shadow_hash_lookup(v, mfn_x(gmfn), shadow_type);
     perfc_incrc(shadow_get_shadow_status);
 
     if ( unlikely(shadow_mode_log_dirty(v->domain) && valid_mfn(smfn)) )
     {
-        struct page_info *page = mfn_to_page(smfn);
-        if ( !(page->count_info & PGC_SH_log_dirty) )
+        struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
+        if ( !(sp->logdirty) )
             shadow_convert_to_log_dirty(v, smfn);
     }
 
@@ -136,16 +134,15 @@ set_fl1_shadow_status(struct vcpu *v, gf
 /* Put an FL1 shadow into the hash table */
 {
     SHADOW_PRINTK("gfn=%"SH_PRI_gfn", type=%08x, smfn=%05lx\n",
-                   gfn_x(gfn), PGC_SH_fl1_shadow, mfn_x(smfn));
+                   gfn_x(gfn), SH_type_fl1_shadow, mfn_x(smfn));
 
     if ( unlikely(shadow_mode_log_dirty(v->domain)) )
         // mark this shadow as a log dirty shadow...
-        set_bit(_PGC_SH_log_dirty, &mfn_to_page(smfn)->count_info);
+        mfn_to_shadow_page(smfn)->logdirty = 1;
     else
-        clear_bit(_PGC_SH_log_dirty, &mfn_to_page(smfn)->count_info);
-
-    shadow_hash_insert(v, gfn_x(gfn),
-                        PGC_SH_fl1_shadow >> PGC_SH_type_shift, smfn);
+        mfn_to_shadow_page(smfn)->logdirty = 0;
+
+    shadow_hash_insert(v, gfn_x(gfn), SH_type_fl1_shadow, smfn);
 }
 
 static inline void 
@@ -161,15 +158,14 @@ set_shadow_status(struct vcpu *v, mfn_t 
 
     if ( unlikely(shadow_mode_log_dirty(d)) )
         // mark this shadow as a log dirty shadow...
-        set_bit(_PGC_SH_log_dirty, &mfn_to_page(smfn)->count_info);
+        mfn_to_shadow_page(smfn)->logdirty = 1;
     else
-        clear_bit(_PGC_SH_log_dirty, &mfn_to_page(smfn)->count_info);
+        mfn_to_shadow_page(smfn)->logdirty = 0;
 
     res = get_page(mfn_to_page(gmfn), d);
     ASSERT(res == 1);
 
-    shadow_hash_insert(v, mfn_x(gmfn), shadow_type >> PGC_SH_type_shift,
-                        smfn);
+    shadow_hash_insert(v, mfn_x(gmfn), shadow_type, smfn);
 }
 
 static inline void 
@@ -177,9 +173,8 @@ delete_fl1_shadow_status(struct vcpu *v,
 /* Remove a shadow from the hash table */
 {
     SHADOW_PRINTK("gfn=%"SH_PRI_gfn", type=%08x, smfn=%05lx\n",
-                   gfn_x(gfn), PGC_SH_fl1_shadow, mfn_x(smfn));
-    shadow_hash_delete(v, gfn_x(gfn),
-                        PGC_SH_fl1_shadow >> PGC_SH_type_shift, smfn);
+                   gfn_x(gfn), SH_type_fl1_shadow, mfn_x(smfn));
+    shadow_hash_delete(v, gfn_x(gfn), SH_type_fl1_shadow, smfn);
 }
 
 static inline void 
@@ -189,8 +184,7 @@ delete_shadow_status(struct vcpu *v, mfn
     SHADOW_PRINTK("d=%d, v=%d, gmfn=%05lx, type=%08x, smfn=%05lx\n",
                    v->domain->domain_id, v->vcpu_id,
                    mfn_x(gmfn), shadow_type, mfn_x(smfn));
-    shadow_hash_delete(v, mfn_x(gmfn),
-                        shadow_type >> PGC_SH_type_shift, smfn);
+    shadow_hash_delete(v, mfn_x(gmfn), shadow_type, smfn);
     put_page(mfn_to_page(gmfn));
 }
 
@@ -394,27 +388,27 @@ static void sh_audit_gw(struct vcpu *v, 
 #if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */
     if ( valid_mfn(gw->l4mfn)
          && valid_mfn((smfn = get_shadow_status(v, gw->l4mfn, 
-                                                PGC_SH_l4_shadow))) )
+                                                SH_type_l4_shadow))) )
         (void) sh_audit_l4_table(v, smfn, _mfn(INVALID_MFN));
     if ( valid_mfn(gw->l3mfn)
          && valid_mfn((smfn = get_shadow_status(v, gw->l3mfn, 
-                                                PGC_SH_l3_shadow))) )
+                                                SH_type_l3_shadow))) )
         (void) sh_audit_l3_table(v, smfn, _mfn(INVALID_MFN));
 #endif /* PAE or 64... */
     if ( valid_mfn(gw->l2mfn) )
     {
         if ( valid_mfn((smfn = get_shadow_status(v, gw->l2mfn, 
-                                                 PGC_SH_l2_shadow))) )
+                                                 SH_type_l2_shadow))) )
             (void) sh_audit_l2_table(v, smfn, _mfn(INVALID_MFN));
 #if GUEST_PAGING_LEVELS == 3
         if ( valid_mfn((smfn = get_shadow_status(v, gw->l2mfn, 
-                                                 PGC_SH_l2h_shadow))) )
+                                                 SH_type_l2h_shadow))) )
             (void) sh_audit_l2_table(v, smfn, _mfn(INVALID_MFN));
 #endif
     }
     if ( valid_mfn(gw->l1mfn)
          && valid_mfn((smfn = get_shadow_status(v, gw->l1mfn, 
-                                                PGC_SH_l1_shadow))) )
+                                                SH_type_l1_shadow))) )
         (void) sh_audit_l1_table(v, smfn, _mfn(INVALID_MFN));
     else if ( gw->l2e
               && (guest_l2e_get_flags(*gw->l2e) & _PAGE_PSE)
@@ -1193,14 +1187,12 @@ static inline void increment_ptr_to_gues
 }
 
 /* All kinds of l1: touch all entries */
-#define _SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p, _done, _code)       \
+#define _SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p, _done, _code)        \
 do {                                                                    \
     int _i;                                                             \
     shadow_l1e_t *_sp = map_shadow_page((_sl1mfn));                     \
-    ASSERT((mfn_to_page(_sl1mfn)->count_info & PGC_SH_type_mask)       \
-           == PGC_SH_l1_shadow                                         \
-           || (mfn_to_page(_sl1mfn)->count_info & PGC_SH_type_mask)    \
-           == PGC_SH_fl1_shadow);                                      \
+    ASSERT(mfn_to_shadow_page(_sl1mfn)->type == SH_type_l1_shadow       \
+           || mfn_to_shadow_page(_sl1mfn)->type == SH_type_fl1_shadow); \
     for ( _i = 0; _i < SHADOW_L1_PAGETABLE_ENTRIES; _i++ )              \
     {                                                                   \
         (_sl1e) = _sp + _i;                                             \
@@ -1214,18 +1206,18 @@ do {                                    
 
 /* 32-bit l1, on PAE or 64-bit shadows: need to walk both pages of shadow */
 #if GUEST_PAGING_LEVELS == 2 && SHADOW_PAGING_LEVELS > 2
-#define SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p, _done,  _code)       \
+#define SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p, _done,  _code)        \
 do {                                                                    \
     int __done = 0;                                                     \
-    _SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p,                         \
+    _SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p,                          \
                          ({ (__done = _done); }), _code);               \
     _sl1mfn = _mfn(mfn_x(_sl1mfn) + 1);                                 \
     if ( !__done )                                                      \
-        _SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p,                     \
+        _SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p,                      \
                              ({ (__done = _done); }), _code);           \
 } while (0)
 #else /* Everything else; l1 shadows are only one page */
-#define SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p, _done, _code)        \
+#define SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p, _done, _code)         \
        _SHADOW_FOREACH_L1E(_sl1mfn, _sl1e, _gl1p, _done, _code)
 #endif
     
@@ -1233,11 +1225,10 @@ do {                                    
 #if GUEST_PAGING_LEVELS == 2 && SHADOW_PAGING_LEVELS > 2
 
 /* 32-bit l2 on PAE/64: four pages, touch every second entry, and avoid Xen */
-#define SHADOW_FOREACH_L2E(_sl2mfn, _sl2e, _gl2p, _done, _xen, _code)    \
+#define SHADOW_FOREACH_L2E(_sl2mfn, _sl2e, _gl2p, _done, _xen, _code)     \
 do {                                                                      \
     int _i, _j, __done = 0;                                               \
-    ASSERT((mfn_to_page(_sl2mfn)->count_info & PGC_SH_type_mask)         \
-           == PGC_SH_l2_32_shadow);                                      \
+    ASSERT(mfn_to_shadow_page(_sl2mfn)->type == SH_type_l2_32_shadow);    \
     for ( _j = 0; _j < 4 && !__done; _j++ )                               \
     {                                                                     \
         shadow_l2e_t *_sp = map_shadow_page(_sl2mfn);                     \
@@ -1260,12 +1251,11 @@ do {                                    
 #elif GUEST_PAGING_LEVELS == 2
 
 /* 32-bit on 32-bit: avoid Xen entries */
-#define SHADOW_FOREACH_L2E(_sl2mfn, _sl2e, _gl2p, _done, _xen, _code)     \
+#define SHADOW_FOREACH_L2E(_sl2mfn, _sl2e, _gl2p, _done, _xen, _code)      \
 do {                                                                       \
     int _i;                                                                \
     shadow_l2e_t *_sp = map_shadow_page((_sl2mfn));                        \
-    ASSERT((mfn_to_page(_sl2mfn)->count_info & PGC_SH_type_mask)          \
-           == PGC_SH_l2_32_shadow);                                       \
+    ASSERT(mfn_to_shadow_page(_sl2mfn)->type == SH_type_l2_32_shadow);     \
     for ( _i = 0; _i < SHADOW_L2_PAGETABLE_ENTRIES; _i++ )                 \
         if ( (!(_xen))                                                     \
              ||                                                            \
@@ -1283,18 +1273,15 @@ do {                                    
 #elif GUEST_PAGING_LEVELS == 3
 
 /* PAE: if it's an l2h, don't touch Xen mappings */
-#define SHADOW_FOREACH_L2E(_sl2mfn, _sl2e, _gl2p, _done, _xen, _code)     \
+#define SHADOW_FOREACH_L2E(_sl2mfn, _sl2e, _gl2p, _done, _xen, _code)      \
 do {                                                                       \
     int _i;                                                                \
     shadow_l2e_t *_sp = map_shadow_page((_sl2mfn));                        \
-    ASSERT((mfn_to_page(_sl2mfn)->count_info & PGC_SH_type_mask)          \
-           == PGC_SH_l2_pae_shadow                                        \
-           || (mfn_to_page(_sl2mfn)->count_info & PGC_SH_type_mask)       \
-           == PGC_SH_l2h_pae_shadow);                                     \
+    ASSERT(mfn_to_shadow_page(_sl2mfn)->type == SH_type_l2_pae_shadow      \
+           || mfn_to_shadow_page(_sl2mfn)->type == SH_type_l2h_pae_shadow);\
     for ( _i = 0; _i < SHADOW_L2_PAGETABLE_ENTRIES; _i++ )                 \
         if ( (!(_xen))                                                     \
-             || ((mfn_to_page(_sl2mfn)->count_info & PGC_SH_type_mask)    \
-                 != PGC_SH_l2h_pae_shadow)                                \
+             || mfn_to_shadow_page(_sl2mfn)->type != SH_type_l2h_pae_shadow\
              || ((_i + (3 * SHADOW_L2_PAGETABLE_ENTRIES))                  \
                  < (HYPERVISOR_VIRT_START >> SHADOW_L2_PAGETABLE_SHIFT)) ) \
         {                                                                  \
@@ -1310,12 +1297,11 @@ do {                                    
 #else 
 
 /* 64-bit l2: touch all entries */
-#define SHADOW_FOREACH_L2E(_sl2mfn, _sl2e, _gl2p, _done, _xen, _code)  \
+#define SHADOW_FOREACH_L2E(_sl2mfn, _sl2e, _gl2p, _done, _xen, _code)   \
 do {                                                                    \
     int _i;                                                             \
     shadow_l2e_t *_sp = map_shadow_page((_sl2mfn));                     \
-    ASSERT((mfn_to_page(_sl2mfn)->count_info & PGC_SH_type_mask)       \
-           == PGC_SH_l2_64_shadow);                                    \
+    ASSERT(mfn_to_shadow_page(_sl2mfn)->type == SH_type_l2_64_shadow);  \
     for ( _i = 0; _i < SHADOW_L2_PAGETABLE_ENTRIES; _i++ )              \
     {                                                                   \
         (_sl2e) = _sp + _i;                                             \
@@ -1332,12 +1318,11 @@ do {                                    
 #if GUEST_PAGING_LEVELS == 4
 
 /* 64-bit l3: touch all entries */
-#define SHADOW_FOREACH_L3E(_sl3mfn, _sl3e, _gl3p, _done, _code)        \
+#define SHADOW_FOREACH_L3E(_sl3mfn, _sl3e, _gl3p, _done, _code)         \
 do {                                                                    \
     int _i;                                                             \
     shadow_l3e_t *_sp = map_shadow_page((_sl3mfn));                     \
-    ASSERT((mfn_to_page(_sl3mfn)->count_info & PGC_SH_type_mask)       \
-           == PGC_SH_l3_64_shadow);                                    \
+    ASSERT(mfn_to_shadow_page(_sl3mfn)->type == SH_type_l3_64_shadow);  \
     for ( _i = 0; _i < SHADOW_L3_PAGETABLE_ENTRIES; _i++ )              \
     {                                                                   \
         (_sl3e) = _sp + _i;                                             \
@@ -1350,12 +1335,11 @@ do {                                    
 } while (0)
 
 /* 64-bit l4: avoid Xen mappings */
-#define SHADOW_FOREACH_L4E(_sl4mfn, _sl4e, _gl4p, _done, _xen, _code)  \
+#define SHADOW_FOREACH_L4E(_sl4mfn, _sl4e, _gl4p, _done, _xen, _code)   \
 do {                                                                    \
     int _i;                                                             \
     shadow_l4e_t *_sp = map_shadow_page((_sl4mfn));                     \
-    ASSERT((mfn_to_page(_sl4mfn)->count_info & PGC_SH_type_mask)       \
-           == PGC_SH_l4_64_shadow);                                    \
+    ASSERT(mfn_to_shadow_page(_sl4mfn)->type == SH_type_l4_64_shadow);  \
     for ( _i = 0; _i < SHADOW_L4_PAGETABLE_ENTRIES; _i++ )              \
     {                                                                   \
         if ( (!(_xen)) || is_guest_l4_slot(_i) )                        \
@@ -1556,12 +1540,12 @@ sh_make_shadow(struct vcpu *v, mfn_t gmf
     SHADOW_DEBUG(MAKE_SHADOW, "(%05lx, %u)=>%05lx\n",
                   mfn_x(gmfn), shadow_type, mfn_x(smfn));
 
-    if ( shadow_type != PGC_SH_l2_32_shadow 
-         && shadow_type != PGC_SH_l2_pae_shadow 
-         && shadow_type != PGC_SH_l2h_pae_shadow 
-         && shadow_type != PGC_SH_l4_64_shadow )
+    if ( shadow_type != SH_type_l2_32_shadow 
+         && shadow_type != SH_type_l2_pae_shadow 
+         && shadow_type != SH_type_l2h_pae_shadow 
+         && shadow_type != SH_type_l4_64_shadow )
         /* Lower-level shadow, not yet linked form a higher level */
-        mfn_to_page(smfn)->up = 0;
+        mfn_to_shadow_page(smfn)->up = 0;
 
     // Create the Xen mappings...
     if ( !shadow_mode_external(v->domain) )
@@ -1569,15 +1553,15 @@ sh_make_shadow(struct vcpu *v, mfn_t gmf
         switch (shadow_type) 
         {
 #if CONFIG_PAGING_LEVELS == 4 && GUEST_PAGING_LEVELS == 4
-        case PGC_SH_l4_shadow:
+        case SH_type_l4_shadow:
             sh_install_xen_entries_in_l4(v, gmfn, smfn); break;
 #endif
 #if CONFIG_PAGING_LEVELS == 3 && GUEST_PAGING_LEVELS == 3
-        case PGC_SH_l2h_shadow:
+        case SH_type_l2h_shadow:
             sh_install_xen_entries_in_l2h(v, smfn); break;
 #endif
 #if CONFIG_PAGING_LEVELS == 2 && GUEST_PAGING_LEVELS == 2
-        case PGC_SH_l2_shadow:
+        case SH_type_l2_shadow:
             sh_install_xen_entries_in_l2(v, gmfn, smfn); break;
 #endif
         default: /* Do nothing */ break;
@@ -1594,7 +1578,7 @@ static mfn_t
 static mfn_t
 make_fl1_shadow(struct vcpu *v, gfn_t gfn)
 {
-    mfn_t smfn = shadow_alloc(v->domain, PGC_SH_fl1_shadow,
+    mfn_t smfn = shadow_alloc(v->domain, SH_type_fl1_shadow,
                                (unsigned long) gfn_x(gfn));
 
     SHADOW_DEBUG(MAKE_SHADOW, "(%" SH_PRI_gfn ")=>%" SH_PRI_mfn "\n",
@@ -1616,7 +1600,7 @@ sh_make_monitor_table(struct vcpu *v)
     {
         struct domain *d = v->domain;
         mfn_t m4mfn;
-        m4mfn = shadow_alloc(d, PGC_SH_monitor_table, 0);
+        m4mfn = shadow_alloc(d, SH_type_monitor_table, 0);
         sh_install_xen_entries_in_l4(v, m4mfn, m4mfn);
         /* Remember the level of this table */
         mfn_to_page(m4mfn)->shadow_flags = 4;
@@ -1626,7 +1610,7 @@ sh_make_monitor_table(struct vcpu *v)
         {
             mfn_t m3mfn; 
             l4_pgentry_t *l4e;
-            m3mfn = shadow_alloc(d, PGC_SH_monitor_table, 0);
+            m3mfn = shadow_alloc(d, SH_type_monitor_table, 0);
             mfn_to_page(m3mfn)->shadow_flags = 3;
             l4e = sh_map_domain_page(m4mfn);
             l4e[0] = l4e_from_pfn(mfn_x(m3mfn), __PAGE_HYPERVISOR);
@@ -1645,13 +1629,13 @@ sh_make_monitor_table(struct vcpu *v)
         l2_pgentry_t *l2e;
         int i;
 
-        m3mfn = shadow_alloc(d, PGC_SH_monitor_table, 0);
+        m3mfn = shadow_alloc(d, SH_type_monitor_table, 0);
         /* Remember the level of this table */
         mfn_to_page(m3mfn)->shadow_flags = 3;
 
         // Install a monitor l2 table in slot 3 of the l3 table.
         // This is used for all Xen entries, including linear maps
-        m2mfn = shadow_alloc(d, PGC_SH_monitor_table, 0);
+        m2mfn = shadow_alloc(d, SH_type_monitor_table, 0);
         mfn_to_page(m2mfn)->shadow_flags = 2;
         l3e = sh_map_domain_page(m3mfn);
         l3e[3] = l3e_from_pfn(mfn_x(m2mfn), _PAGE_PRESENT);
@@ -1675,7 +1659,7 @@ sh_make_monitor_table(struct vcpu *v)
     {
         struct domain *d = v->domain;
         mfn_t m2mfn;
-        m2mfn = shadow_alloc(d, PGC_SH_monitor_table, 0);
+        m2mfn = shadow_alloc(d, SH_type_monitor_table, 0);
         sh_install_xen_entries_in_l2(v, m2mfn, m2mfn);
         /* Remember the level of this table */
         mfn_to_page(m2mfn)->shadow_flags = 2;
@@ -1732,11 +1716,11 @@ static shadow_l3e_t * shadow_get_and_cre
         int r;
         shadow_l4e_t new_sl4e;
         /* No l3 shadow installed: find and install it. */
-        *sl3mfn = get_shadow_status(v, gw->l3mfn, PGC_SH_l3_shadow);
+        *sl3mfn = get_shadow_status(v, gw->l3mfn, SH_type_l3_shadow);
         if ( !valid_mfn(*sl3mfn) ) 
         {
             /* No l3 shadow of this page exists at all: make one. */
-            *sl3mfn = sh_make_shadow(v, gw->l3mfn, PGC_SH_l3_shadow);
+            *sl3mfn = sh_make_shadow(v, gw->l3mfn, SH_type_l3_shadow);
         }
         /* Install the new sl3 table in the sl4e */
         l4e_propagate_from_guest(v, gw->l4e, gw->l4mfn, 
@@ -1772,11 +1756,11 @@ static shadow_l2e_t * shadow_get_and_cre
         int r;
         shadow_l3e_t new_sl3e;
         /* No l2 shadow installed: find and install it. */
-        *sl2mfn = get_shadow_status(v, gw->l2mfn, PGC_SH_l2_shadow);
+        *sl2mfn = get_shadow_status(v, gw->l2mfn, SH_type_l2_shadow);
         if ( !valid_mfn(*sl2mfn) ) 
         {
             /* No l2 shadow of this page exists at all: make one. */
-            *sl2mfn = sh_make_shadow(v, gw->l2mfn, PGC_SH_l2_shadow);
+            *sl2mfn = sh_make_shadow(v, gw->l2mfn, SH_type_l2_shadow);
         }
         /* Install the new sl2 table in the sl3e */
         l3e_propagate_from_guest(v, gw->l3e, gw->l3mfn, 
@@ -1852,11 +1836,11 @@ static shadow_l1e_t * shadow_get_and_cre
         {
             /* Shadowing an actual guest l1 table */
             if ( !valid_mfn(gw->l2mfn) ) return NULL; /* No guest page. */
-            *sl1mfn = get_shadow_status(v, gw->l1mfn, PGC_SH_l1_shadow);
+            *sl1mfn = get_shadow_status(v, gw->l1mfn, SH_type_l1_shadow);
             if ( !valid_mfn(*sl1mfn) ) 
             {
                 /* No l1 shadow of this page exists at all: make one. */
-                *sl1mfn = sh_make_shadow(v, gw->l1mfn, PGC_SH_l1_shadow);
+                *sl1mfn = sh_make_shadow(v, gw->l1mfn, SH_type_l1_shadow);
             }
         }
         /* Install the new sl1 table in the sl2e */
@@ -1891,20 +1875,20 @@ void sh_destroy_l4_shadow(struct vcpu *v
 void sh_destroy_l4_shadow(struct vcpu *v, mfn_t smfn)
 {
     shadow_l4e_t *sl4e;
-    u32 t = mfn_to_page(smfn)->count_info & PGC_SH_type_mask;
+    u32 t = mfn_to_shadow_page(smfn)->type;
     mfn_t gmfn, sl4mfn;
     int xen_mappings;
 
     SHADOW_DEBUG(DESTROY_SHADOW,
                   "%s(%05lx)\n", __func__, mfn_x(smfn));
-    ASSERT(t == PGC_SH_l4_shadow);
+    ASSERT(t == SH_type_l4_shadow);
 
     /* Record that the guest page isn't shadowed any more (in this type) */
-    gmfn = _mfn(mfn_to_page(smfn)->u.inuse.type_info);
+    gmfn = _mfn(mfn_to_shadow_page(smfn)->backpointer);
     delete_shadow_status(v, gmfn, t, smfn);
     shadow_demote(v, gmfn, t);
     /* Take this shadow off the list of root shadows */
-    list_del_init(&mfn_to_page(smfn)->list);
+    list_del_init(&mfn_to_shadow_page(smfn)->list);
 
     /* Decrement refcounts of all the old entries */
     xen_mappings = (!shadow_mode_external(v->domain));
@@ -1925,15 +1909,15 @@ void sh_destroy_l3_shadow(struct vcpu *v
 void sh_destroy_l3_shadow(struct vcpu *v, mfn_t smfn)
 {
     shadow_l3e_t *sl3e;
-    u32 t = mfn_to_page(smfn)->count_info & PGC_SH_type_mask;
+    u32 t = mfn_to_shadow_page(smfn)->type;
     mfn_t gmfn, sl3mfn;
 
     SHADOW_DEBUG(DESTROY_SHADOW,
                   "%s(%05lx)\n", __func__, mfn_x(smfn));
-    ASSERT(t == PGC_SH_l3_shadow);
+    ASSERT(t == SH_type_l3_shadow);
 
     /* Record that the guest page isn't shadowed any more (in this type) */
-    gmfn = _mfn(mfn_to_page(smfn)->u.inuse.type_info);
+    gmfn = _mfn(mfn_to_shadow_page(smfn)->backpointer);
     delete_shadow_status(v, gmfn, t, smfn);
     shadow_demote(v, gmfn, t);
 
@@ -1955,22 +1939,22 @@ void sh_destroy_l2_shadow(struct vcpu *v
 void sh_destroy_l2_shadow(struct vcpu *v, mfn_t smfn)
 {
     shadow_l2e_t *sl2e;
-    u32 t = mfn_to_page(smfn)->count_info & PGC_SH_type_mask;
+    u32 t = mfn_to_shadow_page(smfn)->type;
     mfn_t gmfn, sl2mfn;
     int xen_mappings;
 
     SHADOW_DEBUG(DESTROY_SHADOW,
                   "%s(%05lx)\n", __func__, mfn_x(smfn));
-    ASSERT(t == PGC_SH_l2_shadow 
-           || t == PGC_SH_l2h_pae_shadow);
+    ASSERT(t == SH_type_l2_shadow 
+           || t == SH_type_l2h_pae_shadow);
 
     /* Record that the guest page isn't shadowed any more (in this type) */
-    gmfn = _mfn(mfn_to_page(smfn)->u.inuse.type_info);
+    gmfn = _mfn(mfn_to_shadow_page(smfn)->backpointer);
     delete_shadow_status(v, gmfn, t, smfn);
     shadow_demote(v, gmfn, t);
 #if (GUEST_PAGING_LEVELS == 2) || (GUEST_PAGING_LEVELS == 3)
     /* Take this shadow off the list of root shadows */
-    list_del_init(&mfn_to_page(smfn)->list);
+    list_del_init(&mfn_to_shadow_page(smfn)->list);
 #endif
 
     /* Decrement refcounts of all the old entries */
@@ -1978,7 +1962,7 @@ void sh_destroy_l2_shadow(struct vcpu *v
     xen_mappings = (!shadow_mode_external(v->domain) &&
                     ((GUEST_PAGING_LEVELS == 2) ||
                      ((GUEST_PAGING_LEVELS == 3) &&
-                      (t == PGC_SH_l2h_pae_shadow))));
+                      (t == SH_type_l2h_pae_shadow))));
     SHADOW_FOREACH_L2E(sl2mfn, sl2e, 0, 0, xen_mappings, {
         if ( shadow_l2e_get_flags(*sl2e) & _PAGE_PRESENT ) 
             sh_put_ref(v, shadow_l2e_get_mfn(*sl2e),
@@ -1994,21 +1978,21 @@ void sh_destroy_l1_shadow(struct vcpu *v
 {
     struct domain *d = v->domain;
     shadow_l1e_t *sl1e;
-    u32 t = mfn_to_page(smfn)->count_info & PGC_SH_type_mask;
+    u32 t = mfn_to_shadow_page(smfn)->type;
 
     SHADOW_DEBUG(DESTROY_SHADOW,
                   "%s(%05lx)\n", __func__, mfn_x(smfn));
-    ASSERT(t == PGC_SH_l1_shadow || t == PGC_SH_fl1_shadow);
+    ASSERT(t == SH_type_l1_shadow || t == SH_type_fl1_shadow);
 
     /* Record that the guest page isn't shadowed any more (in this type) */
-    if ( t == PGC_SH_fl1_shadow )
-    {
-        gfn_t gfn = _gfn(mfn_to_page(smfn)->u.inuse.type_info);
+    if ( t == SH_type_fl1_shadow )
+    {
+        gfn_t gfn = _gfn(mfn_to_shadow_page(smfn)->backpointer);
         delete_fl1_shadow_status(v, gfn, smfn);
     }
     else 
     {
-        mfn_t gmfn = _mfn(mfn_to_page(smfn)->u.inuse.type_info);
+        mfn_t gmfn = _mfn(mfn_to_shadow_page(smfn)->backpointer);
         delete_shadow_status(v, gmfn, t, smfn);
         shadow_demote(v, gmfn, t);
     }
@@ -2032,8 +2016,7 @@ void sh_destroy_monitor_table(struct vcp
 void sh_destroy_monitor_table(struct vcpu *v, mfn_t mmfn)
 {
     struct domain *d = v->domain;
-    ASSERT((mfn_to_page(mmfn)->count_info & PGC_SH_type_mask)
-           == PGC_SH_monitor_table);
+    ASSERT(mfn_to_shadow_page(mmfn)->type == SH_type_monitor_table);
 
 #if (CONFIG_PAGING_LEVELS == 4) && (SHADOW_PAGING_LEVELS != 4)
     /* Need to destroy the l3 monitor page in slot 0 too */
@@ -2129,7 +2112,7 @@ static int validate_gl4e(struct vcpu *v,
         gfn_t gl3gfn = guest_l4e_get_gfn(*new_gl4e);
         mfn_t gl3mfn = vcpu_gfn_to_mfn(v, gl3gfn);
         if ( valid_mfn(gl3mfn) )
-            sl3mfn = get_shadow_status(v, gl3mfn, PGC_SH_l3_shadow);
+            sl3mfn = get_shadow_status(v, gl3mfn, SH_type_l3_shadow);
         else
             result |= SHADOW_SET_ERROR;
     }
@@ -2181,7 +2164,7 @@ static int validate_gl3e(struct vcpu *v,
         gfn_t gl2gfn = guest_l3e_get_gfn(*new_gl3e);
         mfn_t gl2mfn = vcpu_gfn_to_mfn(v, gl2gfn);
         if ( valid_mfn(gl2mfn) )
-            sl2mfn = get_shadow_status(v, gl2mfn, PGC_SH_l2_shadow);
+            sl2mfn = get_shadow_status(v, gl2mfn, SH_type_l2_shadow);
         else
             result |= SHADOW_SET_ERROR;
     }
@@ -2225,7 +2208,7 @@ static int validate_gl2e(struct vcpu *v,
         {
             mfn_t gl1mfn = vcpu_gfn_to_mfn(v, gl1gfn);
             if ( valid_mfn(gl1mfn) )
-                sl1mfn = get_shadow_status(v, gl1mfn, PGC_SH_l1_shadow);
+                sl1mfn = get_shadow_status(v, gl1mfn, SH_type_l1_shadow);
             else
                 result |= SHADOW_SET_ERROR;
         }
@@ -2246,8 +2229,7 @@ static int validate_gl2e(struct vcpu *v,
 
 #if SHADOW_PAGING_LEVELS == 3
         reserved_xen_slot = 
-            (((mfn_to_page(sl2mfn)->count_info & PGC_SH_type_mask)
-              == PGC_SH_l2h_pae_shadow) &&
+            ((mfn_to_shadow_page(sl2mfn)->type == SH_type_l2h_pae_shadow) &&
              (shadow_index 
               >= (L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1))));
 #else /* SHADOW_PAGING_LEVELS == 2 */
@@ -2365,7 +2347,7 @@ sh_map_and_validate_gl4e(struct vcpu *v,
 {
 #if GUEST_PAGING_LEVELS >= 4
     return sh_map_and_validate(v, gl4mfn, new_gl4p, size, 
-                                PGC_SH_l4_shadow, 
+                                SH_type_l4_shadow, 
                                 shadow_l4_index, 
                                 validate_gl4e);
 #else // ! GUEST_PAGING_LEVELS >= 4
@@ -2381,7 +2363,7 @@ sh_map_and_validate_gl3e(struct vcpu *v,
 {
 #if GUEST_PAGING_LEVELS >= 4
     return sh_map_and_validate(v, gl3mfn, new_gl3p, size, 
-                                PGC_SH_l3_shadow, 
+                                SH_type_l3_shadow, 
                                 shadow_l3_index, 
                                 validate_gl3e);
 #else // ! GUEST_PAGING_LEVELS >= 4
@@ -2396,7 +2378,7 @@ sh_map_and_validate_gl2e(struct vcpu *v,
                           void *new_gl2p, u32 size)
 {
     return sh_map_and_validate(v, gl2mfn, new_gl2p, size, 
-                                PGC_SH_l2_shadow, 
+                                SH_type_l2_shadow, 
                                 shadow_l2_index, 
                                 validate_gl2e);
 }
@@ -2407,7 +2389,7 @@ sh_map_and_validate_gl2he(struct vcpu *v
 {
 #if GUEST_PAGING_LEVELS == 3
     return sh_map_and_validate(v, gl2mfn, new_gl2p, size, 
-                                PGC_SH_l2h_shadow, 
+                                SH_type_l2h_shadow, 
                                 shadow_l2_index, 
                                 validate_gl2e);
 #else /* Non-PAE guests don't have different kinds of l2 table */
@@ -2422,7 +2404,7 @@ sh_map_and_validate_gl1e(struct vcpu *v,
                           void *new_gl1p, u32 size)
 {
     return sh_map_and_validate(v, gl1mfn, new_gl1p, size, 
-                                PGC_SH_l1_shadow, 
+                                SH_type_l1_shadow, 
                                 shadow_l1_index, 
                                 validate_gl1e);
 }
@@ -2923,8 +2905,8 @@ sh_invlpg(struct vcpu *v, unsigned long 
     // If so, then we'll need to flush the entire TLB (because that's
     // easier than invalidating all of the individual 4K pages).
     //
-    if ( (mfn_to_page(shadow_l2e_get_mfn(sl2e))->count_info &
-          PGC_SH_type_mask) == PGC_SH_fl1_shadow )
+    if ( mfn_to_shadow_page(shadow_l2e_get_mfn(sl2e))->type
+         == SH_type_fl1_shadow )
     {
         local_flush_tlb();
         return 0;
@@ -3284,8 +3266,9 @@ sh_set_toplevel_shadow(struct vcpu *v,
     if ( valid_mfn(smfn) )
     {
         /* Pull this root shadow to the front of the list of roots. */
-        list_del(&mfn_to_page(smfn)->list);
-        list_add(&mfn_to_page(smfn)->list, &d->arch.shadow.toplevel_shadows);
+        struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
+        list_del(&sp->list);
+        list_add(&sp->list, &d->arch.shadow.toplevel_shadows);
     }
     else
     {
@@ -3293,7 +3276,8 @@ sh_set_toplevel_shadow(struct vcpu *v,
         shadow_prealloc(d, SHADOW_MAX_ORDER); 
         /* Shadow the page. */
         smfn = sh_make_shadow(v, gmfn, root_type);
-        list_add(&mfn_to_page(smfn)->list, &d->arch.shadow.toplevel_shadows);
+        list_add(&mfn_to_shadow_page(smfn)->list, 
+                 &d->arch.shadow.toplevel_shadows);
     }
     ASSERT(valid_mfn(smfn));
     
@@ -3444,7 +3428,7 @@ sh_update_cr3(struct vcpu *v)
 #if GUEST_PAGING_LEVELS == 2
     if ( shadow_remove_write_access(v, gmfn, 2, 0) != 0 )
         flush_tlb_mask(v->domain->domain_dirty_cpumask); 
-    sh_set_toplevel_shadow(v, 0, gmfn, PGC_SH_l2_shadow);
+    sh_set_toplevel_shadow(v, 0, gmfn, SH_type_l2_shadow);
 #elif GUEST_PAGING_LEVELS == 3
     /* PAE guests have four shadow_table entries, based on the 
      * current values of the guest's four l3es. */
@@ -3473,15 +3457,15 @@ sh_update_cr3(struct vcpu *v)
                 gl2gfn = guest_l3e_get_gfn(gl3e[i]);
                 gl2mfn = vcpu_gfn_to_mfn(v, gl2gfn);
                 sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3) 
-                                       ? PGC_SH_l2h_shadow 
-                                       : PGC_SH_l2_shadow);
+                                       ? SH_type_l2h_shadow 
+                                       : SH_type_l2_shadow);
             }
         }
     }
 #elif GUEST_PAGING_LEVELS == 4
     if ( shadow_remove_write_access(v, gmfn, 4, 0) != 0 )
         flush_tlb_mask(v->domain->domain_dirty_cpumask);
-    sh_set_toplevel_shadow(v, 0, gmfn, PGC_SH_l4_shadow);
+    sh_set_toplevel_shadow(v, 0, gmfn, SH_type_l4_shadow);
 #else
 #error This should never happen 
 #endif
@@ -3667,19 +3651,19 @@ void sh_clear_shadow_entry(struct vcpu *
 void sh_clear_shadow_entry(struct vcpu *v, void *ep, mfn_t smfn)
 /* Blank out a single shadow entry */
 {
-    switch (mfn_to_page(smfn)->count_info & PGC_SH_type_mask) 
-    {
-    case PGC_SH_l1_shadow:
+    switch ( mfn_to_shadow_page(smfn)->type )
+    {
+    case SH_type_l1_shadow:
         shadow_set_l1e(v, ep, shadow_l1e_empty(), smfn); break;
-    case PGC_SH_l2_shadow:
+    case SH_type_l2_shadow:
 #if GUEST_PAGING_LEVELS == 3
-    case PGC_SH_l2h_shadow:
+    case SH_type_l2h_shadow:
 #endif
         shadow_set_l2e(v, ep, shadow_l2e_empty(), smfn); break;
 #if GUEST_PAGING_LEVELS >= 4
-    case PGC_SH_l3_shadow:
+    case SH_type_l3_shadow:
         shadow_set_l3e(v, ep, shadow_l3e_empty(), smfn); break;
-    case PGC_SH_l4_shadow:
+    case SH_type_l4_shadow:
         shadow_set_l4e(v, ep, shadow_l4e_empty(), smfn); break;
 #endif
     default: BUG(); /* Called with the wrong kind of shadow. */
@@ -3703,7 +3687,7 @@ int sh_remove_l1_shadow(struct vcpu *v, 
              && (mfn_x(shadow_l2e_get_mfn(*sl2e)) == mfn_x(sl1mfn)) )
         {
             shadow_set_l2e(v, sl2e, shadow_l2e_empty(), sl2mfn);
-            if ( (mfn_to_page(sl1mfn)->count_info & PGC_SH_type_mask) == 0 )
+            if ( mfn_to_shadow_page(sl1mfn)->type == 0 )
                 /* This breaks us cleanly out of the FOREACH macro */
                 done = 1;
         }
@@ -3726,7 +3710,7 @@ int sh_remove_l2_shadow(struct vcpu *v, 
              && (mfn_x(shadow_l3e_get_mfn(*sl3e)) == mfn_x(sl2mfn)) )
         {
             shadow_set_l3e(v, sl3e, shadow_l3e_empty(), sl3mfn);
-            if ( (mfn_to_page(sl2mfn)->count_info & PGC_SH_type_mask) == 0 )
+            if ( mfn_to_shadow_page(sl2mfn)->type == 0 )
                 /* This breaks us cleanly out of the FOREACH macro */
                 done = 1;
         }
@@ -3748,7 +3732,7 @@ int sh_remove_l3_shadow(struct vcpu *v, 
              && (mfn_x(shadow_l4e_get_mfn(*sl4e)) == mfn_x(sl3mfn)) )
         {
             shadow_set_l4e(v, sl4e, shadow_l4e_empty(), sl4mfn);
-            if ( (mfn_to_page(sl3mfn)->count_info & PGC_SH_type_mask) == 0 )
+            if ( mfn_to_shadow_page(sl3mfn)->type == 0 )
                 /* This breaks us cleanly out of the FOREACH macro */
                 done = 1;
         }
@@ -3986,7 +3970,7 @@ int sh_audit_l1_table(struct vcpu *v, mf
     int done = 0;
     
     /* Follow the backpointer */
-    gl1mfn = _mfn(mfn_to_page(sl1mfn)->u.inuse.type_info);
+    gl1mfn = _mfn(mfn_to_shadow_page(sl1mfn)->backpointer);
     gl1e = gp = sh_map_domain_page(gl1mfn);
     SHADOW_FOREACH_L1E(sl1mfn, sl1e, &gl1e, done, {
 
@@ -4068,7 +4052,7 @@ int sh_audit_l2_table(struct vcpu *v, mf
 #endif
 
     /* Follow the backpointer */
-    gl2mfn = _mfn(mfn_to_page(sl2mfn)->u.inuse.type_info);
+    gl2mfn = _mfn(mfn_to_shadow_page(sl2mfn)->backpointer);
     gl2e = gp = sh_map_domain_page(gl2mfn);
     SHADOW_FOREACH_L2E(sl2mfn, sl2e, &gl2e, done, xen_mappings, {
 
@@ -4083,7 +4067,7 @@ int sh_audit_l2_table(struct vcpu *v, mf
             gmfn = (guest_l2e_get_flags(*gl2e) & _PAGE_PSE)  
                 ? get_fl1_shadow_status(v, gfn)
                 : get_shadow_status(v, audit_gfn_to_mfn(v, gfn, gl2mfn), 
-                                    PGC_SH_l1_shadow);
+                                    SH_type_l1_shadow);
             if ( mfn_x(gmfn) != mfn_x(mfn) )
                 AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn
                            " (--> %" SH_PRI_mfn ")"
@@ -4109,7 +4093,7 @@ int sh_audit_l3_table(struct vcpu *v, mf
     int done = 0;
 
     /* Follow the backpointer */
-    gl3mfn = _mfn(mfn_to_page(sl3mfn)->u.inuse.type_info);
+    gl3mfn = _mfn(mfn_to_shadow_page(sl3mfn)->backpointer);
     gl3e = gp = sh_map_domain_page(gl3mfn);
     SHADOW_FOREACH_L3E(sl3mfn, sl3e, &gl3e, done, {
 
@@ -4125,8 +4109,8 @@ int sh_audit_l3_table(struct vcpu *v, mf
                                      (GUEST_PAGING_LEVELS == 3 
                                       && !shadow_mode_external(v->domain)
                                       && (guest_index(gl3e) % 4) == 3)
-                                     ? PGC_SH_l2h_pae_shadow
-                                     : PGC_SH_l2_shadow);
+                                     ? SH_type_l2h_pae_shadow
+                                     : SH_type_l2_shadow);
             if ( mfn_x(gmfn) != mfn_x(mfn) )
                 AUDIT_FAIL(3, "bad translation: gfn %" SH_PRI_gfn
                            " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn,
@@ -4148,7 +4132,7 @@ int sh_audit_l4_table(struct vcpu *v, mf
     int xen_mappings = !shadow_mode_external(v->domain);
 
     /* Follow the backpointer */
-    gl4mfn = _mfn(mfn_to_page(sl4mfn)->u.inuse.type_info);
+    gl4mfn = _mfn(mfn_to_shadow_page(sl4mfn)->backpointer);
     gl4e = gp = sh_map_domain_page(gl4mfn);
     SHADOW_FOREACH_L4E(sl4mfn, sl4e, &gl4e, done, xen_mappings,
     {
@@ -4161,7 +4145,7 @@ int sh_audit_l4_table(struct vcpu *v, mf
             gfn = guest_l4e_get_gfn(*gl4e);
             mfn = shadow_l4e_get_mfn(*sl4e);
             gmfn = get_shadow_status(v, audit_gfn_to_mfn(v, gfn, gl4mfn), 
-                                     PGC_SH_l3_shadow);
+                                     SH_type_l3_shadow);
             if ( mfn_x(gmfn) != mfn_x(mfn) )
                 AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn
                            " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn,
diff -r a8d2b1393b76 -r 6f0d8434d23f xen/arch/x86/mm/shadow/private.h
--- a/xen/arch/x86/mm/shadow/private.h  Tue Nov 21 18:09:23 2006 -0800
+++ b/xen/arch/x86/mm/shadow/private.h  Thu Nov 23 17:40:28 2006 +0000
@@ -129,6 +129,97 @@ extern void shadow_audit_p2m(struct doma
 #undef SHADOW_LEVELS
 #endif /* CONFIG_PAGING_LEVELS == 4 */
 
+/******************************************************************************
+ * Page metadata for shadow pages.
+ */
+
+struct shadow_page_info
+{
+    union {
+        /* When in use, guest page we're a shadow of */
+        unsigned long backpointer;
+        /* When free, order of the freelist we're on */
+        unsigned int order;
+    };
+    union {
+        /* When in use, next shadow in this hash chain */
+        struct shadow_page_info *next_shadow;
+        /* When free, TLB flush time when freed */
+        u32 tlbflush_timestamp;
+    };
+    struct {
+        unsigned int type:4;      /* What kind of shadow is this? */
+        unsigned int pinned:1;    /* Is the shadow pinned? */
+        unsigned int logdirty:1;  /* Was it made in log-dirty mode? */
+        unsigned int count:26;    /* Reference count */
+        u32 mbz;                  /* Must be zero: this is where the owner 
+                                   * field lives in a non-shadow page */
+    } __attribute__((packed));
+    union {
+        /* For unused shadow pages, a list of pages of this order; 
+         * for top-level shadows, a list of other top-level shadows */
+        struct list_head list;
+        /* For lower-level shadows, a higher entry that points at us */
+        paddr_t up;
+    };
+};
+
+/* The structure above *must* be the same size as a struct page_info
+ * from mm.h, since we'll be using the same space in the frametable. 
+ * Also, the mbz field must line up with the owner field of normal 
+ * pages, so they look properly like anonymous/xen pages. */
+static inline void shadow_check_page_struct_offsets(void) {
+    BUILD_BUG_ON(sizeof (struct shadow_page_info) 
+                 != sizeof (struct page_info));
+    BUILD_BUG_ON(offsetof(struct shadow_page_info, mbz) 
+                 != offsetof(struct page_info, u.inuse._domain));
+};
+
+/* Shadow type codes */
+#define SH_type_none           (0U) /* on the shadow free list */
+#define SH_type_min_shadow     (1U)
+#define SH_type_l1_32_shadow   (1U) /* shadowing a 32-bit L1 guest page */
+#define SH_type_fl1_32_shadow  (2U) /* L1 shadow for a 32b 4M superpage */
+#define SH_type_l2_32_shadow   (3U) /* shadowing a 32-bit L2 guest page */
+#define SH_type_l1_pae_shadow  (4U) /* shadowing a pae L1 page */
+#define SH_type_fl1_pae_shadow (5U) /* L1 shadow for pae 2M superpg */
+#define SH_type_l2_pae_shadow  (6U) /* shadowing a pae L2-low page */
+#define SH_type_l2h_pae_shadow (7U) /* shadowing a pae L2-high page */
+#define SH_type_l1_64_shadow   (8U) /* shadowing a 64-bit L1 page */
+#define SH_type_fl1_64_shadow  (9U) /* L1 shadow for 64-bit 2M superpg */
+#define SH_type_l2_64_shadow  (10U) /* shadowing a 64-bit L2 page */
+#define SH_type_l3_64_shadow  (11U) /* shadowing a 64-bit L3 page */
+#define SH_type_l4_64_shadow  (12U) /* shadowing a 64-bit L4 page */
+#define SH_type_max_shadow    (12U)
+#define SH_type_p2m_table     (13U) /* in use as the p2m table */
+#define SH_type_monitor_table (14U) /* in use as a monitor table */
+#define SH_type_unused        (15U)
+
+/*
+ * Definitions for the shadow_flags field in page_info.
+ * These flags are stored on *guest* pages...
+ * Bits 1-13 are encodings for the shadow types.
+ */
+#define SHF_page_type_mask \
+    (((1u << (SH_type_max_shadow + 1u)) - 1u) - \
+     ((1u << SH_type_min_shadow) - 1u))
+
+#define SHF_L1_32   (1u << SH_type_l1_32_shadow)
+#define SHF_FL1_32  (1u << SH_type_fl1_32_shadow)
+#define SHF_L2_32   (1u << SH_type_l2_32_shadow)
+#define SHF_L1_PAE  (1u << SH_type_l1_pae_shadow)
+#define SHF_FL1_PAE (1u << SH_type_fl1_pae_shadow)
+#define SHF_L2_PAE  (1u << SH_type_l2_pae_shadow)
+#define SHF_L2H_PAE (1u << SH_type_l2h_pae_shadow)
+#define SHF_L1_64   (1u << SH_type_l1_64_shadow)
+#define SHF_FL1_64  (1u << SH_type_fl1_64_shadow)
+#define SHF_L2_64   (1u << SH_type_l2_64_shadow)
+#define SHF_L3_64   (1u << SH_type_l3_64_shadow)
+#define SHF_L4_64   (1u << SH_type_l4_64_shadow)
+
+/* Used for hysteresis when automatically unhooking mappings on fork/exit */
+#define SHF_unhooked_mappings (1u<<31)
+
 
 /******************************************************************************
  * Various function declarations 
@@ -173,12 +264,14 @@ void sh_install_xen_entries_in_l2(struct
 // Override mfn_to_page from asm/page.h, which was #include'd above,
 // in order to make it work with our mfn type.
 #undef mfn_to_page
-#define mfn_to_page(_mfn) (frame_table + mfn_x(_mfn))
+#define mfn_to_page(_m) (frame_table + mfn_x(_m))
+#define mfn_to_shadow_page(_m) ((struct shadow_page_info *)mfn_to_page(_m))
 
 // Override page_to_mfn from asm/page.h, which was #include'd above,
 // in order to make it work with our mfn type.
 #undef page_to_mfn
 #define page_to_mfn(_pg) (_mfn((_pg) - frame_table))
+#define shadow_page_to_mfn(_spg) (page_to_mfn((struct page_info *)_spg))
 
 // Override mfn_valid from asm/page.h, which was #include'd above,
 // in order to make it work with our mfn type.
@@ -189,28 +282,24 @@ static inline void *
 static inline void *
 sh_map_domain_page(mfn_t mfn)
 {
-    /* XXX Using the monitor-table as a map will happen here  */
     return map_domain_page(mfn_x(mfn));
 }
 
 static inline void 
 sh_unmap_domain_page(void *p) 
 {
-    /* XXX Using the monitor-table as a map will happen here  */
     unmap_domain_page(p);
 }
 
 static inline void *
 sh_map_domain_page_global(mfn_t mfn)
 {
-    /* XXX Using the monitor-table as a map will happen here  */
     return map_domain_page_global(mfn_x(mfn));
 }
 
 static inline void 
 sh_unmap_domain_page_global(void *p) 
 {
-    /* XXX Using the monitor-table as a map will happen here  */
     unmap_domain_page_global(p);
 }
 
@@ -253,8 +342,7 @@ sh_mfn_is_a_page_table(mfn_t gmfn)
 
 
 /**************************************************************************/
-/* Shadow-page refcounting. See comment in shadow-common.c about the  
- * use of struct page_info fields for shadow pages */
+/* Shadow-page refcounting. */
 
 void sh_destroy_shadow(struct vcpu *v, mfn_t smfn);
 
@@ -264,27 +352,26 @@ static inline void sh_get_ref(mfn_t smfn
 static inline void sh_get_ref(mfn_t smfn, paddr_t entry_pa)
 {
     u32 x, nx;
-    struct page_info *page = mfn_to_page(smfn);
+    struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
 
     ASSERT(mfn_valid(smfn));
 
-    x = page->count_info & PGC_SH_count_mask;
+    x = sp->count;
     nx = x + 1;
 
-    if ( unlikely(nx & ~PGC_SH_count_mask) )
+    if ( unlikely(nx >= 1U<<26) )
     {
         SHADOW_PRINTK("shadow ref overflow, gmfn=%" PRtype_info " smfn=%lx\n",
-                       page->u.inuse.type_info, mfn_x(smfn));
+                       sp->backpointer, mfn_x(smfn));
         domain_crash_synchronous();
     }
     
     /* Guarded by the shadow lock, so no need for atomic update */
-    page->count_info &= ~PGC_SH_count_mask;
-    page->count_info |= nx;
+    sp->count = nx;
 
     /* We remember the first shadow entry that points to each shadow. */
-    if ( entry_pa != 0 && page->up == 0 ) 
-        page->up = entry_pa;
+    if ( entry_pa != 0 && sp->up == 0 ) 
+        sp->up = entry_pa;
 }
 
 
@@ -293,31 +380,27 @@ static inline void sh_put_ref(struct vcp
 static inline void sh_put_ref(struct vcpu *v, mfn_t smfn, paddr_t entry_pa)
 {
     u32 x, nx;
-    struct page_info *page = mfn_to_page(smfn);
+    struct shadow_page_info *sp = mfn_to_shadow_page(smfn);
 
     ASSERT(mfn_valid(smfn));
-    ASSERT(page_get_owner(page) == NULL);
+    ASSERT(sp->mbz == 0);
 
     /* If this is the entry in the up-pointer, remove it */
-    if ( entry_pa != 0 && page->up == entry_pa ) 
-        page->up = 0;
-
-    x = page->count_info & PGC_SH_count_mask;
+    if ( entry_pa != 0 && sp->up == entry_pa ) 
+        sp->up = 0;
+
+    x = sp->count;
     nx = x - 1;
 
     if ( unlikely(x == 0) ) 
     {
-        SHADOW_PRINTK("shadow ref underflow, smfn=%lx oc=%08x t=%" 
-                       PRtype_info "\n",
-                       mfn_x(smfn),
-                       page->count_info & PGC_SH_count_mask,
-                       page->u.inuse.type_info);
+        SHADOW_PRINTK("shadow ref underflow, smfn=%lx oc=%08x t=%#x\n",
+                      mfn_x(smfn), sp->count, sp->type);
         domain_crash_synchronous();
     }
 
     /* Guarded by the shadow lock, so no need for atomic update */
-    page->count_info &= ~PGC_SH_count_mask;
-    page->count_info |= nx;
+    sp->count = nx;
 
     if ( unlikely(nx == 0) ) 
         sh_destroy_shadow(v, smfn);
@@ -327,27 +410,27 @@ static inline void sh_put_ref(struct vcp
 /* Pin a shadow page: take an extra refcount and set the pin bit. */
 static inline void sh_pin(mfn_t smfn)
 {
-    struct page_info *page;
+    struct shadow_page_info *sp;
     
     ASSERT(mfn_valid(smfn));
-    page = mfn_to_page(smfn);
-    if ( !(page->count_info & PGC_SH_pinned) ) 
+    sp = mfn_to_shadow_page(smfn);
+    if ( !(sp->pinned) ) 
     {
         sh_get_ref(smfn, 0);
-        page->count_info |= PGC_SH_pinned;
+        sp->pinned = 1;
     }
 }
 
 /* Unpin a shadow page: unset the pin bit and release the extra ref. */
 static inline void sh_unpin(struct vcpu *v, mfn_t smfn)
 {
-    struct page_info *page;
+    struct shadow_page_info *sp;
     
     ASSERT(mfn_valid(smfn));
-    page = mfn_to_page(smfn);
-    if ( page->count_info & PGC_SH_pinned )
+    sp = mfn_to_shadow_page(smfn);
+    if ( sp->pinned )
     {
-        page->count_info &= ~PGC_SH_pinned;
+        sp->pinned = 0;
         sh_put_ref(v, smfn, 0);
     }
 }
diff -r a8d2b1393b76 -r 6f0d8434d23f xen/arch/x86/mm/shadow/types.h
--- a/xen/arch/x86/mm/shadow/types.h    Tue Nov 21 18:09:23 2006 -0800
+++ b/xen/arch/x86/mm/shadow/types.h    Thu Nov 23 17:40:28 2006 +0000
@@ -281,9 +281,9 @@ static inline guest_l2e_t guest_l2e_from
 #define guest_l2_table_offset(a) l2_table_offset_32(a)
 
 /* The shadow types needed for the various levels. */
-#define PGC_SH_l1_shadow  PGC_SH_l1_32_shadow
-#define PGC_SH_l2_shadow  PGC_SH_l2_32_shadow
-#define PGC_SH_fl1_shadow PGC_SH_fl1_32_shadow
+#define SH_type_l1_shadow  SH_type_l1_32_shadow
+#define SH_type_l2_shadow  SH_type_l2_32_shadow
+#define SH_type_fl1_shadow SH_type_fl1_32_shadow
 
 #else /* GUEST_PAGING_LEVELS != 2 */
 
@@ -381,16 +381,16 @@ static inline guest_l4e_t guest_l4e_from
 
 /* The shadow types needed for the various levels. */
 #if GUEST_PAGING_LEVELS == 3
-#define PGC_SH_l1_shadow  PGC_SH_l1_pae_shadow
-#define PGC_SH_fl1_shadow PGC_SH_fl1_pae_shadow
-#define PGC_SH_l2_shadow  PGC_SH_l2_pae_shadow
-#define PGC_SH_l2h_shadow PGC_SH_l2h_pae_shadow
+#define SH_type_l1_shadow  SH_type_l1_pae_shadow
+#define SH_type_fl1_shadow SH_type_fl1_pae_shadow
+#define SH_type_l2_shadow  SH_type_l2_pae_shadow
+#define SH_type_l2h_shadow SH_type_l2h_pae_shadow
 #else
-#define PGC_SH_l1_shadow  PGC_SH_l1_64_shadow
-#define PGC_SH_fl1_shadow PGC_SH_fl1_64_shadow
-#define PGC_SH_l2_shadow  PGC_SH_l2_64_shadow
-#define PGC_SH_l3_shadow  PGC_SH_l3_64_shadow
-#define PGC_SH_l4_shadow  PGC_SH_l4_64_shadow
+#define SH_type_l1_shadow  SH_type_l1_64_shadow
+#define SH_type_fl1_shadow SH_type_fl1_64_shadow
+#define SH_type_l2_shadow  SH_type_l2_64_shadow
+#define SH_type_l3_shadow  SH_type_l3_64_shadow
+#define SH_type_l4_shadow  SH_type_l4_64_shadow
 #endif
 
 #endif /* GUEST_PAGING_LEVELS != 2 */
diff -r a8d2b1393b76 -r 6f0d8434d23f xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Tue Nov 21 18:09:23 2006 -0800
+++ b/xen/include/asm-x86/mm.h  Thu Nov 23 17:40:28 2006 +0000
@@ -20,11 +20,7 @@ struct page_info
 struct page_info
 {
     /* Each frame can be threaded onto a doubly-linked list. */
-    union {
-        struct list_head list;
-        /* Shadow uses this field as an up-pointer in lower-level shadows */
-        paddr_t up;
-    };
+    struct list_head list;
 
     /* Reference count and various PGC_xxx flags and fields. */
     u32 count_info;
@@ -59,11 +55,11 @@ struct page_info
         u32 tlbflush_timestamp;
 
         /*
-         * Guest pages with a shadow. This does not conflict with
+         * Guest pages with a shadow.  This does not conflict with
          * tlbflush_timestamp since page table pages are explicitly not
          * tracked for TLB-flush avoidance when a guest runs in shadow mode.
          */
-        u32 shadow_flags;
+        unsigned long shadow_flags;
     };
 };
 
@@ -102,38 +98,6 @@ struct page_info
 #define PGC_page_table      (1U<<_PGC_page_table)
  /* 29-bit count of references to this frame. */
 #define PGC_count_mask      ((1U<<29)-1)
-
-/* shadow uses the count_info on shadow pages somewhat differently */
-/* NB: please coordinate any changes here with the SHF's in shadow.h */
-#define PGC_SH_none           (0U<<28) /* on the shadow free list */
-#define PGC_SH_min_shadow     (1U<<28)
-#define PGC_SH_l1_32_shadow   (1U<<28) /* shadowing a 32-bit L1 guest page */
-#define PGC_SH_fl1_32_shadow  (2U<<28) /* L1 shadow for a 32b 4M superpage */
-#define PGC_SH_l2_32_shadow   (3U<<28) /* shadowing a 32-bit L2 guest page */
-#define PGC_SH_l1_pae_shadow  (4U<<28) /* shadowing a pae L1 page */
-#define PGC_SH_fl1_pae_shadow (5U<<28) /* L1 shadow for pae 2M superpg */
-#define PGC_SH_l2_pae_shadow  (6U<<28) /* shadowing a pae L2-low page */
-#define PGC_SH_l2h_pae_shadow (7U<<28) /* shadowing a pae L2-high page */
-#define PGC_SH_l1_64_shadow   (8U<<28) /* shadowing a 64-bit L1 page */
-#define PGC_SH_fl1_64_shadow  (9U<<28) /* L1 shadow for 64-bit 2M superpg */
-#define PGC_SH_l2_64_shadow  (10U<<28) /* shadowing a 64-bit L2 page */
-#define PGC_SH_l3_64_shadow  (11U<<28) /* shadowing a 64-bit L3 page */
-#define PGC_SH_l4_64_shadow  (12U<<28) /* shadowing a 64-bit L4 page */
-#define PGC_SH_max_shadow    (12U<<28)
-#define PGC_SH_p2m_table     (13U<<28) /* in use as the p2m table */
-#define PGC_SH_monitor_table (14U<<28) /* in use as a monitor table */
-#define PGC_SH_unused        (15U<<28)
-
-#define PGC_SH_type_mask     (15U<<28)
-#define PGC_SH_type_shift          28
-
-#define PGC_SH_pinned         (1U<<27)
-
-#define _PGC_SH_log_dirty          26
-#define PGC_SH_log_dirty      (1U<<26)
-
-/* 26 bit ref count for shadow pages */
-#define PGC_SH_count_mask    ((1U<<26) - 1)
 
 /* We trust the slab allocator in slab.c, and our use of it. */
 #define PageSlab(page)     (1)
diff -r a8d2b1393b76 -r 6f0d8434d23f xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Tue Nov 21 18:09:23 2006 -0800
+++ b/xen/include/asm-x86/shadow.h      Thu Nov 23 17:40:28 2006 +0000
@@ -577,32 +577,6 @@ shadow_guest_physmap_remove_page(struct 
 shadow_guest_physmap_remove_page(struct domain *d, unsigned long gfn,
                                   unsigned long mfn);
 
-/*
- * Definitions for the shadow_flags field in page_info.
- * These flags are stored on *guest* pages...
- * Bits 1-13 are encodings for the shadow types.
- */
-#define PGC_SH_type_to_index(_type) ((_type) >> PGC_SH_type_shift)
-#define SHF_page_type_mask \
-    (((1u << (PGC_SH_type_to_index(PGC_SH_max_shadow) + 1u)) - 1u) - \
-     ((1u << PGC_SH_type_to_index(PGC_SH_min_shadow)) - 1u))
-
-#define SHF_L1_32   (1u << PGC_SH_type_to_index(PGC_SH_l1_32_shadow))
-#define SHF_FL1_32  (1u << PGC_SH_type_to_index(PGC_SH_fl1_32_shadow))
-#define SHF_L2_32   (1u << PGC_SH_type_to_index(PGC_SH_l2_32_shadow))
-#define SHF_L1_PAE  (1u << PGC_SH_type_to_index(PGC_SH_l1_pae_shadow))
-#define SHF_FL1_PAE (1u << PGC_SH_type_to_index(PGC_SH_fl1_pae_shadow))
-#define SHF_L2_PAE  (1u << PGC_SH_type_to_index(PGC_SH_l2_pae_shadow))
-#define SHF_L2H_PAE (1u << PGC_SH_type_to_index(PGC_SH_l2h_pae_shadow))
-#define SHF_L1_64   (1u << PGC_SH_type_to_index(PGC_SH_l1_64_shadow))
-#define SHF_FL1_64  (1u << PGC_SH_type_to_index(PGC_SH_fl1_64_shadow))
-#define SHF_L2_64   (1u << PGC_SH_type_to_index(PGC_SH_l2_64_shadow))
-#define SHF_L3_64   (1u << PGC_SH_type_to_index(PGC_SH_l3_64_shadow))
-#define SHF_L4_64   (1u << PGC_SH_type_to_index(PGC_SH_l4_64_shadow))
-
-/* Used for hysteresis when automatically unhooking mappings on fork/exit */
-#define SHF_unhooked_mappings (1u<<31)
-
 /* 
  * Allocation of shadow pages 
  */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [XEN] Use a separate struct shadow_page_info for shadow pages, Xen patchbot-unstable <=