[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] x86: cacheability page attributes



Track cacheability of a page (as requested by the owning guest) to avoid
virual aliases with different cacheability. This is done by splitting
PGT_writable_page into a set of 8 attributes, each being writeable plus
one of the possible caching types (3 PTE bits). It is being complicated
by the fact that now transitions between non-read-only page types must
be supported (e.g. writeable/WB -> writeable/UC), requiring some special
casing in the page table handling code.

Depends on the previously submitted TLB/cache flushing patch.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: 2007-08-08/xen/arch/x86/mm.c
===================================================================
--- 2007-08-08.orig/xen/arch/x86/mm.c   2007-08-21 14:18:00.000000000 +0200
+++ 2007-08-08/xen/arch/x86/mm.c        2007-08-21 14:18:39.000000000 +0200
@@ -147,6 +147,14 @@ struct page_info *frame_table;
 unsigned long max_page;
 unsigned long total_pages;
 
+#define PAGE_CACHE_ATTRS (_PAGE_PAT|_PAGE_PCD|_PAGE_PWT)
+
+#define l1_disallow_mask(d) (!(d)->iomem_caps || \
+                             !rangeset_is_empty((d)->iomem_caps) || \
+                             !rangeset_is_empty((d)->arch.ioport_caps) ? \
+                             L1_DISALLOW_MASK : \
+                             L1_DISALLOW_MASK|PAGE_CACHE_ATTRS)
+
 #ifdef CONFIG_COMPAT
 l2_pgentry_t *compat_idle_pg_table_l2 = NULL;
 #define l3_disallow_mask(d) (!is_pv_32on64_domain(d) ?  \
@@ -278,9 +286,10 @@ void share_xen_page_with_guest(
 
     spin_lock(&d->page_alloc_lock);
 
-    /* The incremented type count pins as writable or read-only. */
     page->u.inuse.type_info  = (readonly ? PGT_none : PGT_writable_page);
-    page->u.inuse.type_info |= PGT_validated | 1;
+    if ( readonly || d != dom_io )
+        /* The incremented type count pins as writable or read-only. */
+        page->u.inuse.type_info |= PGT_validated | 1;
 
     page_set_owner(page, d);
     wmb(); /* install valid domain ptr before updating refcnt. */
@@ -539,6 +548,74 @@ static int get_page_and_type_from_pagenr
     return 1;
 }
 
+static unsigned long get_writable_type(unsigned int flags)
+{
+    unsigned long type = PGT_none;
+
+    if ( flags & _PAGE_RW )
+        type = PGT_writable_page;
+    if ( flags & _PAGE_PWT )
+        type |= PGT_pwt_mask | PGT_writable_page;
+    if ( flags & _PAGE_PCD )
+        type |= PGT_pcd_mask | PGT_writable_page;
+#ifdef CONFIG_PAT
+    if ( flags & _PAGE_PAT )
+        type |= PGT_pat_mask | PGT_writable_page;
+#endif
+    BUG_ON(!(type & PGT_writable_page));
+
+    return type;
+}
+
+static int alloc_writable_page(struct page_info *page, unsigned long type)
+{
+    unsigned long mfn = page_to_mfn(page);
+    unsigned int flags = 0;
+    int ret;
+
+    if ( page_get_owner(page) == dom_io )
+        return 1;
+#ifdef __i386__
+    if ( mfn >= ((DIRECTMAP_VIRT_END - DIRECTMAP_VIRT_START) >> PAGE_SHIFT) )
+        return 1;
+#endif
+
+    if ( type & PGT_pwt_mask )
+        flags |= _PAGE_PWT;
+    if ( type & PGT_pcd_mask )
+        flags |= _PAGE_PCD;
+#ifdef CONFIG_PAT
+    if ( type & PGT_pat_mask )
+        flags |= _PAGE_PAT;
+#endif
+    ret = map_pages_to_xen((unsigned long)mfn_to_virt(mfn), mfn, 1,
+                           PAGE_HYPERVISOR | flags);
+    if ( ret == 0 )
+        return 1;
+
+    MEM_LOG("Error %d changing cacheability of mfn %lx", ret, mfn);
+    return 0;
+}
+
+static void free_writable_page(struct page_info *page)
+{
+    unsigned long mfn = page_to_mfn(page);
+
+    if ( page_get_owner(page) == dom_io )
+        return;
+#ifdef __i386__
+    if ( mfn >= ((DIRECTMAP_VIRT_END - DIRECTMAP_VIRT_START) >> PAGE_SHIFT) )
+        return;
+#endif
+
+    if ( map_pages_to_xen((unsigned long)mfn_to_virt(mfn), mfn, 1,
+                          PAGE_HYPERVISOR) )
+    {
+        printk("Reverting cacheability for %lx failed\n", mfn);
+        BUG();
+    }
+}
+
 /*
  * We allow root tables to map each other (a.k.a. linear page tables). It
  * needs some special care with reference counts and access permissions:
@@ -599,15 +676,16 @@ get_page_from_l1e(
     l1_pgentry_t l1e, struct domain *d)
 {
     unsigned long mfn = l1e_get_pfn(l1e);
+    unsigned int flags = l1e_get_flags(l1e);
     struct page_info *page = mfn_to_page(mfn);
     int okay;
 
-    if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
+    if ( !(flags & _PAGE_PRESENT) )
         return 1;
 
-    if ( unlikely(l1e_get_flags(l1e) & L1_DISALLOW_MASK) )
+    if ( unlikely(flags & l1_disallow_mask(d)) )
     {
-        MEM_LOG("Bad L1 flags %x", l1e_get_flags(l1e) & L1_DISALLOW_MASK);
+        MEM_LOG("Bad L1 flags %x", flags & l1_disallow_mask(d));
         return 0;
     }
 
@@ -637,9 +715,9 @@ get_page_from_l1e(
      * contribute to writeable mapping refcounts.  (This allows the
      * qemu-dm helper process in dom0 to map the domain's memory without
      * messing up the count of "real" writable mappings.) */
-    okay = (((l1e_get_flags(l1e) & _PAGE_RW) && 
+    okay = (((flags & (_PAGE_RW|PAGE_CACHE_ATTRS)) &&
              !(unlikely(paging_mode_external(d) && (d != current->domain))))
-            ? get_page_and_type(page, d, PGT_writable_page)
+            ? get_page_and_type(page, d, get_writable_type(flags))
             : get_page(page, d));
     if ( !okay )
     {
@@ -832,7 +910,7 @@ void put_page_from_l1e(l1_pgentry_t l1e,
 
     /* Remember we didn't take a type-count of foreign writable mappings
      * to paging-external domains */
-    if ( (l1e_get_flags(l1e) & _PAGE_RW) && 
+    if ( (l1e_get_flags(l1e) & (_PAGE_RW|PAGE_CACHE_ATTRS)) &&
          !(unlikely((e != d) && paging_mode_external(e))) )
     {
         put_page_and_type(page);
@@ -1333,6 +1411,60 @@ static inline int update_intpte(intpte_t
                   _t ## e_get_intpte(_o), _t ## e_get_intpte(_n),   \
                   (_m), (_v))
 
+/*
+ * Present->present transitions referencing the same page with old and new
+ * attributes resulting in (different) PGT_writable_page types and with the
+ * type use count being 1 must be special cased, as the transition would
+ * otherwise fail.
+ */
+static int transition_writable_page(l1_pgentry_t *pl1e, l1_pgentry_t ol1e,
+                                    l1_pgentry_t nl1e, unsigned long gl1mfn,
+                                    int do_cmpxchg)
+{
+    struct page_info *page = l1e_get_page(nl1e);
+    unsigned long type = get_writable_type(l1e_get_flags(ol1e));
+    unsigned long nx = type | 2;
+    unsigned long x = type | PGT_validated | 1;
+
+    if ( cmpxchg(&page->u.inuse.type_info, x, nx) == x )
+    {
+        /*
+         * The adjustment is now safe because the refcnt is 2 and validated
+         * bit is clear => non-free ops will spin or fail, and a racing free
+         * is illegal (will crash domain below).
+         */
+        type = get_writable_type(l1e_get_flags(nl1e));
+        if ( alloc_writable_page(page, type) )
+        {
+            x = nx;
+            nx = type | PGT_validated | 1;
+            if ( cmpxchg(&page->u.inuse.type_info, x, nx) == x )
+            {
+                if ( do_cmpxchg )
+                {
+                    intpte_t t = l1e_get_intpte(ol1e);
+
+                    if ( paging_cmpxchg_guest_entry(current,
+                                                    &l1e_get_intpte(*pl1e),
+                                                    &t,
+                                                    l1e_get_intpte(nl1e),
+                                                    _mfn(gl1mfn)) )
+                        return t == l1e_get_intpte(ol1e);
+                }
+                else if ( UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, current) )
+                    return 1;
+            }
+            domain_crash(current->domain);
+            return 0;
+        }
+        page->u.inuse.type_info |= PGT_validated;
+        /* Drop the extra reference. */
+        put_page_type(page);
+    }
+
+    return -1;
+}
+
 /* Update the L1 entry at pl1e to new value nl1e. */
 static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, 
                         unsigned long gl1mfn)
@@ -1356,19 +1488,31 @@ static int mod_l1_entry(l1_pgentry_t *pl
         ASSERT((mfn & ~(PADDR_MASK >> PAGE_SHIFT)) == 0);
         nl1e = l1e_from_pfn(mfn, l1e_get_flags(nl1e));
 
-        if ( unlikely(l1e_get_flags(nl1e) & L1_DISALLOW_MASK) )
+        if ( unlikely(l1e_get_flags(nl1e) & l1_disallow_mask(d)) )
         {
             MEM_LOG("Bad L1 flags %x",
-                    l1e_get_flags(nl1e) & L1_DISALLOW_MASK);
+                    l1e_get_flags(nl1e) & l1_disallow_mask(d));
             return 0;
         }
 
         adjust_guest_l1e(nl1e, d);
 
-        /* Fast path for identical mapping, r/w and presence. */
-        if ( !l1e_has_changed(ol1e, nl1e, _PAGE_RW | _PAGE_PRESENT) )
+        /* Fast path for identical mapping, r/w, cacheability, and presence. */
+        if ( !l1e_has_changed(ol1e, nl1e,
+                              _PAGE_RW | _PAGE_PRESENT | PAGE_CACHE_ATTRS) )
             return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, current);
 
+        if ( !l1e_has_changed(ol1e, nl1e, _PAGE_PRESENT) &&
+             (l1e_get_flags(ol1e) & (_PAGE_RW | PAGE_CACHE_ATTRS)) &&
+             (l1e_get_flags(nl1e) & (_PAGE_RW | PAGE_CACHE_ATTRS)) &&
+             mfn_valid(l1e_get_pfn(nl1e)) )
+        {
+            int ret = transition_writable_page(pl1e, ol1e, nl1e, gl1mfn, 0);
+
+            if ( ret >= 0 )
+                return ret;
+        }
+
         if ( unlikely(!get_page_from_l1e(nl1e, FOREIGNDOM)) )
             return 0;
         
@@ -1563,10 +1707,13 @@ static int mod_l4_entry(struct domain *d
 
 #endif
 
-int alloc_page_type(struct page_info *page, unsigned long type)
+static int alloc_page_type(struct page_info *page, unsigned long type)
 {
     struct domain *owner = page_get_owner(page);
 
+    if ( type & PGT_writable_page )
+        return alloc_writable_page(page, type);
+
     /* A page table is dirtied when its type count becomes non-zero. */
     if ( likely(owner != NULL) )
         paging_mark_dirty(owner, page_to_mfn(page));
@@ -1600,6 +1747,12 @@ void free_page_type(struct page_info *pa
     struct domain *owner = page_get_owner(page);
     unsigned long gmfn;
 
+    if ( type & PGT_writable_page )
+    {
+        free_writable_page(page);
+        return;
+    }
+
     if ( likely(owner != NULL) )
     {
         /*
@@ -1669,11 +1822,13 @@ void put_page_type(struct page_info *pag
 
         if ( unlikely((nx & PGT_count_mask) == 0) )
         {
-            if ( unlikely((nx & PGT_type_mask) <= PGT_l4_page_table) &&
+            if ( (unlikely((nx & PGT_type_mask) <= PGT_l4_page_table) ||
+                  unlikely((nx & PGT_type_mask) > PGT_writable_page)) &&
                  likely(nx & PGT_validated) )
             {
                 /*
-                 * Page-table pages must be unvalidated when count is zero. The
+                 * Page-table pages and writable pages with non-default
+                 * cacheability must be unvalidated when count is zero. The
                  * 'free' is safe because the refcnt is non-zero and validated
                  * bit is clear => other ops will spin or fail.
                  */
@@ -1742,7 +1897,7 @@ int get_page_type(struct page_info *page
                 if ( unlikely(!cpus_empty(mask)) &&
                      /* Shadow mode: track only writable pages. */
                      (!shadow_mode_enabled(page_get_owner(page)) ||
-                      ((nx & PGT_type_mask) == PGT_writable_page)) )
+                      (nx & PGT_writable_page)) )
                 {
                     perfc_incr(need_flush_tlb_flush);
                     flush_tlb_mask(mask);
@@ -3304,8 +3459,30 @@ static int ptwr_emulated_update(
     ASSERT((page->u.inuse.type_info & PGT_count_mask) != 0);
     ASSERT(page_get_owner(page) == d);
 
+    pl1e = (l1_pgentry_t *)((unsigned long)map_domain_page(mfn)
+                            + (addr & ~PAGE_MASK));
+    ol1e = do_cmpxchg ? l1e_from_intpte(old) : *pl1e;
+
     /* Check the new PTE. */
     nl1e = l1e_from_intpte(val);
+    adjust_guest_l1e(nl1e, d);
+
+    if ( (l1e_get_flags(nl1e) & _PAGE_PRESENT) &&
+         !l1e_has_changed(ol1e, nl1e, _PAGE_PRESENT) &&
+         l1e_has_changed(ol1e, nl1e, _PAGE_RW | PAGE_CACHE_ATTRS) &&
+         (l1e_get_flags(ol1e) & (_PAGE_RW | PAGE_CACHE_ATTRS)) &&
+         (l1e_get_flags(nl1e) & (_PAGE_RW | PAGE_CACHE_ATTRS)) &&
+         mfn_valid(l1e_get_pfn(nl1e)) )
+    {
+        int ret = transition_writable_page(pl1e, ol1e, nl1e, mfn, do_cmpxchg);
+
+        if ( ret >= 0 )
+        {
+            unmap_domain_page(pl1e);
+            return ret ? X86EMUL_OKAY : X86EMUL_RETRY;
+        }
+    }
+
     if ( unlikely(!get_page_from_l1e(nl1e, d)) )
     {
         if ( (CONFIG_PAGING_LEVELS >= 3) && is_pv_32bit_domain(d) &&
@@ -3324,21 +3501,17 @@ static int ptwr_emulated_update(
         }
         else
         {
+            unmap_domain_page(pl1e);
             MEM_LOG("ptwr_emulate: could not get_page_from_l1e()");
             return X86EMUL_UNHANDLEABLE;
         }
     }
 
-    adjust_guest_l1e(nl1e, d);
-
     /* Checked successfully: do the update (write or cmpxchg). */
-    pl1e = map_domain_page(mfn);
-    pl1e = (l1_pgentry_t *)((unsigned long)pl1e + (addr & ~PAGE_MASK));
     if ( do_cmpxchg )
     {
         int okay;
         intpte_t t = old;
-        ol1e = l1e_from_intpte(old);
 
         okay = paging_cmpxchg_guest_entry(v, &l1e_get_intpte(*pl1e),
                                           &t, val, _mfn(mfn));
@@ -3351,12 +3524,8 @@ static int ptwr_emulated_update(
             return X86EMUL_CMPXCHG_FAILED;
         }
     }
-    else
-    {
-        ol1e = *pl1e;
-        if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v) )
-            BUG();
-    }
+    else if ( !UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, mfn, v) )
+        BUG();
 
     unmap_domain_page(pl1e);
 
@@ -3470,11 +3639,27 @@ void free_xen_pagetable(void *v)
         free_domheap_page(virt_to_page(v));
 }
 
+static inline unsigned int l1f_to_l2f(unsigned int flags)
+{
+    if ( flags & _PAGE_PAT )
+        flags = (flags & ~_PAGE_PAT) | _PAGE_PSE_PAT;
+    return flags | _PAGE_PSE;
+}
+
+static inline unsigned int l2f_to_l1f(unsigned int flags)
+{
+    ASSERT(flags & _PAGE_PSE);
+    flags &= ~_PAGE_PSE;
+    if ( flags & _PAGE_PSE_PAT )
+        flags = (flags & ~_PAGE_PSE_PAT) | _PAGE_PAT;
+    return flags;
+}
+
 int map_pages_to_xen(
     unsigned long virt,
     unsigned long mfn,
     unsigned long nr_mfns,
-    unsigned long flags)
+    unsigned int flags)
 {
     l2_pgentry_t *pl2e, ol2e;
     l1_pgentry_t *pl1e, ol1e;
@@ -3493,11 +3678,15 @@ int map_pages_to_xen(
         {
             /* Super-page mapping. */
             ol2e = *pl2e;
-            l2e_write_atomic(pl2e, l2e_from_pfn(mfn, flags|_PAGE_PSE));
+            l2e_write_atomic(pl2e, l2e_from_pfn(mfn, l1f_to_l2f(flags)));
 
             if ( (l2e_get_flags(ol2e) & _PAGE_PRESENT) )
             {
-                flush_one_local((void *)virt, FLUSH_TLB_GLOBAL|2);
+                flush_one_global((void *)virt,
+                                 ((l2e_get_flags(ol2e) ^ l1f_to_l2f(flags)) &
+                                  l1f_to_l2f(PAGE_CACHE_ATTRS)) ?
+                                 FLUSH_CACHE|FLUSH_TLB_GLOBAL|2 :
+                                 FLUSH_TLB_GLOBAL|2);
                 if ( !(l2e_get_flags(ol2e) & _PAGE_PSE) )
                     free_xen_pagetable(mfn_to_virt(l2e_get_pfn(ol2e)));
             }
@@ -3512,31 +3701,73 @@ int map_pages_to_xen(
             if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
             {
                 pl1e = alloc_xen_pagetable();
+                if ( pl1e == NULL )
+                    return -ENOMEM;
                 clear_page(pl1e);
                 l2e_write(pl2e, l2e_from_pfn(virt_to_mfn(pl1e),
                                              __PAGE_HYPERVISOR));
             }
             else if ( l2e_get_flags(*pl2e) & _PAGE_PSE )
             {
+                if ( (l2e_get_pfn(*pl2e) & ~(L1_PAGETABLE_ENTRIES - 1)) +
+                     l1_table_offset(virt) == mfn &&
+                     ((l2f_to_l1f(l2e_get_flags(*pl2e)) ^ flags) &
+                      ~(_PAGE_ACCESSED|_PAGE_DIRTY)) == 0 )
+                {
+                    virt    += 1UL << L1_PAGETABLE_SHIFT;
+                    mfn     += 1UL;
+                    nr_mfns -= 1UL;
+                    continue;
+                }
+
                 pl1e = alloc_xen_pagetable();
+                if ( pl1e == NULL )
+                    return -ENOMEM;
                 for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
                     l1e_write(&pl1e[i],
                               l1e_from_pfn(l2e_get_pfn(*pl2e) + i,
-                                           l2e_get_flags(*pl2e) & ~_PAGE_PSE));
+                                           l2f_to_l1f(l2e_get_flags(*pl2e))));
                 l2e_write_atomic(pl2e, l2e_from_pfn(virt_to_mfn(pl1e),
                                                     __PAGE_HYPERVISOR));
-                flush_one_local((void *)virt, FLUSH_TLB_GLOBAL|2);
+                flush_one_global((void *)virt, FLUSH_TLB_GLOBAL|2);
             }
 
             pl1e  = l2e_to_l1e(*pl2e) + l1_table_offset(virt);
             ol1e  = *pl1e;
             l1e_write_atomic(pl1e, l1e_from_pfn(mfn, flags));
             if ( (l1e_get_flags(ol1e) & _PAGE_PRESENT) )
-                local_flush_tlb_one(virt);
+                flush_one_global((void *)virt,
+                                 ((l1e_get_flags(ol1e) ^ flags)
+                                  & PAGE_CACHE_ATTRS) ?
+                                 FLUSH_CACHE|FLUSH_TLB_GLOBAL|1 :
+                                 FLUSH_TLB_GLOBAL|1);
 
             virt    += 1UL << L1_PAGETABLE_SHIFT;
             mfn     += 1UL;
             nr_mfns -= 1UL;
+
+            if ( !map_small_pages &&
+                 flags == PAGE_HYPERVISOR &&
+                 ( nr_mfns == 0 ||
+                   ((((virt>>PAGE_SHIFT) | mfn) & ((1<<PAGETABLE_ORDER)-1)) == 
0)) )
+            {
+                unsigned long base_mfn;
+
+                pl1e  = l2e_to_l1e(*pl2e);
+                base_mfn = l1e_get_pfn(*pl1e);
+                for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++, pl1e++ )
+                    if ( l1e_get_pfn(*pl1e) != base_mfn + i ||
+                         l1e_get_flags(*pl1e) != flags )
+                        break;
+                if ( i == L1_PAGETABLE_ENTRIES )
+                {
+                    ol2e = *pl2e;
+                    l2e_write(pl2e, l2e_from_pfn(base_mfn, l1f_to_l2f(flags)));
+                    flush_one_global((void *)(virt - (1UL << 
L2_PAGETABLE_SHIFT)),
+                                     FLUSH_TLB_GLOBAL|2);
+                    free_xen_pagetable(mfn_to_virt(l2e_get_pfn(ol2e)));
+                }
+            }
         }
     }
 
Index: 2007-08-08/xen/arch/x86/mm/shadow/common.c
===================================================================
--- 2007-08-08.orig/xen/arch/x86/mm/shadow/common.c     2007-08-21 
14:15:47.000000000 +0200
+++ 2007-08-08/xen/arch/x86/mm/shadow/common.c  2007-08-08 12:03:19.000000000 
+0200
@@ -1354,7 +1354,7 @@ static void sh_hash_audit_bucket(struct 
             /* Bad shadow flags on guest page? */
             BUG_ON( !(gpg->shadow_flags & (1<<sp->type)) );
             /* Bad type count on guest page? */
-            if ( (gpg->u.inuse.type_info & PGT_type_mask) == PGT_writable_page 
+            if ( (gpg->u.inuse.type_info & PGT_writable_page)
                  && (gpg->u.inuse.type_info & PGT_count_mask) != 0 )
             {
                 SHADOW_ERROR("MFN %#lx shadowed (by %#"PRI_mfn")"
Index: 2007-08-08/xen/arch/x86/mm/shadow/multi.c
===================================================================
--- 2007-08-08.orig/xen/arch/x86/mm/shadow/multi.c      2007-08-21 
14:15:47.000000000 +0200
+++ 2007-08-08/xen/arch/x86/mm/shadow/multi.c   2007-08-08 12:03:19.000000000 
+0200
@@ -4261,8 +4261,7 @@ audit_gfn_to_mfn(struct vcpu *v, gfn_t g
     if ( !shadow_mode_translate(v->domain) )
         return _mfn(gfn_x(gfn));
     
-    if ( (mfn_to_page(gmfn)->u.inuse.type_info & PGT_type_mask)
-         != PGT_writable_page ) 
+    if ( !(mfn_to_page(gmfn)->u.inuse.type_info & PGT_writable_page) )
         return _mfn(gfn_x(gfn)); /* This is a paging-disabled shadow */
     else 
         return gfn_to_mfn(v->domain, gfn_x(gfn));
Index: 2007-08-08/xen/include/asm-x86/mm.h
===================================================================
--- 2007-08-08.orig/xen/include/asm-x86/mm.h    2007-08-21 14:15:47.000000000 
+0200
+++ 2007-08-08/xen/include/asm-x86/mm.h 2007-08-08 12:03:19.000000000 +0200
@@ -64,24 +64,35 @@ struct page_info
 };
 
  /* The following page types are MUTUALLY EXCLUSIVE. */
-#define PGT_none            (0U<<29) /* no special uses of this page */
-#define PGT_l1_page_table   (1U<<29) /* using this page as an L1 page table? */
-#define PGT_l2_page_table   (2U<<29) /* using this page as an L2 page table? */
-#define PGT_l3_page_table   (3U<<29) /* using this page as an L3 page table? */
-#define PGT_l4_page_table   (4U<<29) /* using this page as an L4 page table? */
-#define PGT_gdt_page        (5U<<29) /* using this page in a GDT? */
-#define PGT_ldt_page        (6U<<29) /* using this page in an LDT? */
-#define PGT_writable_page   (7U<<29) /* has writable mappings of this page? */
-#define PGT_type_mask       (7U<<29) /* Bits 29-31. */
+#define PGT_none            (0U<<28) /* no special uses of this page */
+#define PGT_l1_page_table   (1U<<28) /* using this page as an L1 page table? */
+#define PGT_l2_page_table   (2U<<28) /* using this page as an L2 page table? */
+#define PGT_l3_page_table   (3U<<28) /* using this page as an L3 page table? */
+#define PGT_l4_page_table   (4U<<28) /* using this page as an L4 page table? */
+#define PGT_gdt_page        (5U<<28) /* using this page in a GDT? */
+#define PGT_ldt_page        (6U<<28) /* using this page in an LDT? */
+#define PGT_writable_page   (0x8U<<28) /* has writable mappings of this page? 
*/
+#define PGT_pwt_mask        (0x1U<<28) /* (l1e & _PAGE_PWT) mirror */
+#define PGT_pcd_mask        (0x2U<<28) /* (l1e & _PAGE_PCD) mirror */
+#define PGT_wb_page         (0x8U<<28) /* WB cached writable page? */
+#define PGT_wt_page         (0x9U<<28) /* WT cached writable page? */
+#define PGT_ucm_page        (0xAU<<28) /* UC- cached writable page? */
+#define PGT_uc_page         (0xBU<<28) /* UC cached writable page? */
+#ifdef CONFIG_PAT
+#define PGT_pat_mask        (0x4U<<28) /* (l1e & _PAGE_PAT) mirror */
+#define PGT_wc_page         (0xCU<<28) /* WC cached writable page? */
+#define PGT_wp_page         (0xDU<<28) /* WP cached writable page? */
+#endif
+#define PGT_type_mask       (0xFU<<28) /* Bits 28-31. */
 
  /* Owning guest has pinned this page to its current type? */
-#define _PGT_pinned         28
+#define _PGT_pinned         22
 #define PGT_pinned          (1U<<_PGT_pinned)
  /* Has this page been validated for use as its current type? */
-#define _PGT_validated      27
+#define _PGT_validated      21
 #define PGT_validated       (1U<<_PGT_validated)
  /* PAE only: is this an L2 page directory containing Xen-private mappings? */
-#define _PGT_pae_xen_l2     26
+#define _PGT_pae_xen_l2     20
 #define PGT_pae_xen_l2      (1U<<_PGT_pae_xen_l2)
 
  /* 16-bit count of uses of this frame as its current type. */
@@ -144,7 +155,6 @@ extern unsigned long max_page;
 extern unsigned long total_pages;
 void init_frametable(void);
 
-int alloc_page_type(struct page_info *page, unsigned long type);
 void free_page_type(struct page_info *page, unsigned long type);
 int _shadow_mode_refcounts(struct domain *d);
 
Index: 2007-08-08/xen/include/asm-x86/page.h
===================================================================
--- 2007-08-08.orig/xen/include/asm-x86/page.h  2007-08-21 14:15:47.000000000 
+0200
+++ 2007-08-08/xen/include/asm-x86/page.h       2007-08-08 12:03:19.000000000 
+0200
@@ -355,13 +355,13 @@ void free_xen_pagetable(void *v);
 l2_pgentry_t *virt_to_xen_l2e(unsigned long v);
 
 /* Map machine page range in Xen virtual address space. */
-#define MAP_SMALL_PAGES (1UL<<16) /* don't use superpages for the mapping */
+#define MAP_SMALL_PAGES (1U<<31) /* don't use superpages for the mapping */
 int
 map_pages_to_xen(
     unsigned long virt,
     unsigned long mfn,
     unsigned long nr_mfns,
-    unsigned long flags);
+    unsigned int flags);
 void destroy_xen_mappings(unsigned long v, unsigned long e);
 
 #endif /* !__ASSEMBLY__ */
Index: 2007-08-08/xen/include/asm-x86/x86_32/page-3level.h
===================================================================
--- 2007-08-08.orig/xen/include/asm-x86/x86_32/page-3level.h    2007-08-21 
14:15:47.000000000 +0200
+++ 2007-08-08/xen/include/asm-x86/x86_32/page-3level.h 2007-08-08 
12:03:19.000000000 +0200
@@ -85,6 +85,6 @@ typedef l3_pgentry_t root_pgentry_t;
 #define get_pte_flags(x) (((int)((x) >> 32) & ~0xFFF) | ((int)(x) & 0xFFF))
 #define put_pte_flags(x) (((intpte_t)((x) & ~0xFFF) << 32) | ((x) & 0xFFF))
 
-#define L3_DISALLOW_MASK 0xFFFFF1E6U /* must-be-zero */
+#define L3_DISALLOW_MASK 0xFFFFF1FEU /* must-be-zero */
 
 #endif /* __X86_32_PAGE_3LEVEL_H__ */
Index: 2007-08-08/xen/include/asm-x86/x86_32/page.h
===================================================================
--- 2007-08-08.orig/xen/include/asm-x86/x86_32/page.h   2007-08-21 
14:15:47.000000000 +0200
+++ 2007-08-08/xen/include/asm-x86/x86_32/page.h        2007-08-08 
12:03:19.000000000 +0200
@@ -33,13 +33,13 @@ extern unsigned int PAGE_HYPERVISOR_NOCA
     (_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_GNTTAB)
 
 /*
- * Disallow unused flag bits plus PAT, PSE and GLOBAL.
+ * Disallow unused flag bits plus PAT/PSE and GLOBAL.
  * Permit the NX bit if the hardware supports it.
  */
 #define BASE_DISALLOW_MASK (0xFFFFF180U & ~_PAGE_NX)
 
 #define L1_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_GNTTAB)
-#define L2_DISALLOW_MASK (BASE_DISALLOW_MASK)
+#define L2_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_PCD | _PAGE_PWT)
 
 #endif /* __X86_32_PAGE_H__ */
 
Index: 2007-08-08/xen/include/asm-x86/x86_64/page.h
===================================================================
--- 2007-08-08.orig/xen/include/asm-x86/x86_64/page.h   2007-08-21 
14:15:47.000000000 +0200
+++ 2007-08-08/xen/include/asm-x86/x86_64/page.h        2007-08-08 
12:03:19.000000000 +0200
@@ -105,18 +105,18 @@ typedef l4_pgentry_t root_pgentry_t;
 #define _PAGE_NX     (cpu_has_nx ? _PAGE_NX_BIT : 0U)
 
 /*
- * Disallow unused flag bits plus PAT, PSE and GLOBAL.
+ * Disallow unused flag bits plus PAT/PSE and GLOBAL.
  * Permit the NX bit if the hardware supports it.
  * Note that range [62:52] is available for software use on x86/64.
  */
 #define BASE_DISALLOW_MASK (0xFF800180U & ~_PAGE_NX)
 
 #define L1_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_GNTTAB)
-#define L2_DISALLOW_MASK (BASE_DISALLOW_MASK)
-#define L3_DISALLOW_MASK (BASE_DISALLOW_MASK)
-#define L4_DISALLOW_MASK (BASE_DISALLOW_MASK)
+#define L2_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_PCD | _PAGE_PWT)
+#define L3_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_PCD | _PAGE_PWT)
+#define L4_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_PCD | _PAGE_PWT)
 
-#define COMPAT_L3_DISALLOW_MASK 0xFFFFF1E6U
+#define COMPAT_L3_DISALLOW_MASK 0xFFFFF1FEU
 
 #define PAGE_HYPERVISOR         (__PAGE_HYPERVISOR         | _PAGE_GLOBAL)
 #define PAGE_HYPERVISOR_NOCACHE (__PAGE_HYPERVISOR_NOCACHE | _PAGE_GLOBAL)



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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.