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] [IA64] Make P2M semantics match x86

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [IA64] Make P2M semantics match x86
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 28 Mar 2007 10:10:20 -0700
Delivery-date: Wed, 28 Mar 2007 10:10:35 -0700
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 awilliam@xxxxxxxxxxxx
# Date 1174922117 21600
# Node ID fa77ec03afd609b095ce5813a776123b176c8b67
# Parent  be1017157768e8d6d5d5552cf0008d81d611b1bb
[IA64] Make P2M semantics match x86

So far the ia64 p2m has the semantic similar to
(the x86 p2m) + (page reference count).
But the differece from the x86 p2m have caused the breakage and work around.
This patch make the ia64 p2m semantic same as x86 to solve it.
- get_page() only for grant table page mapping and foreign domain page
  mapping.
- put_page() only for those pages.
- guest_physmap_remove_page() doesn't touch PGC_allocated bit.

Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
 xen/arch/ia64/xen/mm.c    |  175 ++++++++++++++++++----------------------------
 xen/include/asm-ia64/mm.h |    2 
 2 files changed, 73 insertions(+), 104 deletions(-)

diff -r be1017157768 -r fa77ec03afd6 xen/arch/ia64/xen/mm.c
--- a/xen/arch/ia64/xen/mm.c    Thu Mar 22 09:30:54 2007 -0600
+++ b/xen/arch/ia64/xen/mm.c    Mon Mar 26 09:15:17 2007 -0600
@@ -208,46 +208,6 @@ alloc_dom_xen_and_dom_io(void)
     BUG_ON(dom_io == NULL);
 }
 
-// heavily depends on the struct page_info layout.
-// if (page_get_owner(page) == d &&
-//     test_and_clear_bit(_PGC_allocated, &page->count_info)) {
-//     put_page(page);
-// }
-static void
-try_to_clear_PGC_allocate(struct domain* d, struct page_info* page)
-{
-    u32 _d, _nd;
-    u64 x, nx, y;
-
-    _d = pickle_domptr(d);
-    y = *((u64*)&page->count_info);
-    do {
-        x = y;
-        _nd = x >> 32;
-        nx = x - 1;
-        __clear_bit(_PGC_allocated, &nx);
-
-        if (unlikely(!(x & PGC_allocated)) || unlikely(_nd != _d)) {
-            struct domain* nd = unpickle_domptr(_nd);
-            if (nd == NULL) {
-                gdprintk(XENLOG_INFO, "gnttab_transfer: "
-                        "Bad page %p: ed=%p(%u) 0x%x, "
-                        "sd=%p 0x%x,"
-                        " caf=%016lx, taf=%" PRtype_info "\n",
-                        (void *) page_to_mfn(page),
-                        d, d->domain_id, _d,
-                        nd, _nd,
-                        x,
-                        page->u.inuse.type_info);
-            }
-            break;
-        }
-
-        BUG_ON((nx & PGC_count_mask) < 1);
-        y = cmpxchg((u64*)&page->count_info, x, nx);
-    } while (unlikely(y != x));
-}
-
 static void
 mm_teardown_pte(struct domain* d, volatile pte_t* pte, unsigned long offset)
 {
@@ -267,22 +227,25 @@ mm_teardown_pte(struct domain* d, volati
     if (!mfn_valid(mfn))
         return;
     page = mfn_to_page(mfn);
-    // struct page_info corresponding to mfn may exist or not depending
-    // on CONFIG_VIRTUAL_FRAME_TABLE.
-    // This check is too easy.
-    // The right way is to check whether this page is of io area or acpi pages
+    // page might be pte page for p2m exposing. check it.
     if (page_get_owner(page) == NULL) {
         BUG_ON(page->count_info != 0);
         return;
     }
+    // struct page_info corresponding to mfn may exist or not depending
+    // on CONFIG_VIRTUAL_FRAME_TABLE.
+    // The above check is too easy.
+    // The right way is to check whether this page is of io area or acpi pages
 
     if (pte_pgc_allocated(old_pte)) {
         BUG_ON(page_get_owner(page) != d);
         BUG_ON(get_gpfn_from_mfn(mfn) == INVALID_M2P_ENTRY);
         set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY);
-        try_to_clear_PGC_allocate(d, page);
-    }
-    put_page(page);
+        if (test_and_clear_bit(_PGC_allocated, &page->count_info))
+            put_page(page);
+    } else {
+        put_page(page);
+    }
 }
 
 static void
@@ -770,7 +733,6 @@ __assign_new_domain_page(struct domain *
 {
     struct page_info *p;
     unsigned long maddr;
-    int ret;
 
     BUG_ON(!pte_none(*pte));
 
@@ -791,8 +753,6 @@ __assign_new_domain_page(struct domain *
                maddr);
     }
 
-    ret = get_page(p, d);
-    BUG_ON(ret == 0);
     set_gpfn_from_mfn(page_to_mfn(p), mpaddr >> PAGE_SHIFT);
     // clear_page() and set_gpfn_from_mfn() become visible before set_pte_rel()
     // because set_pte_rel() has release semantics
@@ -893,11 +853,9 @@ assign_domain_page(struct domain *d,
                    unsigned long mpaddr, unsigned long physaddr)
 {
     struct page_info* page = mfn_to_page(physaddr >> PAGE_SHIFT);
-    int ret;
 
     BUG_ON((physaddr & GPFN_IO_MASK) != GPFN_MEM);
-    ret = get_page(page, d);
-    BUG_ON(ret == 0);
+    BUG_ON(page->count_info != (PGC_allocated | 1));
     set_gpfn_from_mfn(physaddr >> PAGE_SHIFT, mpaddr >> PAGE_SHIFT);
     // because __assign_domain_page() uses set_pte_rel() which has
     // release semantics, smp_mb() isn't needed.
@@ -1086,6 +1044,29 @@ assign_domain_mach_page(struct domain *d
 }
 
 static void
+adjust_page_count_info(struct page_info* page)
+{
+    struct domain* d = page_get_owner(page);
+    BUG_ON((page->count_info & PGC_count_mask) != 1);
+    if (d != NULL) {
+        int ret = get_page(page, d);
+        BUG_ON(ret == 0);
+    } else {
+        u64 x, nx, y;
+
+        y = *((u64*)&page->count_info);
+        do {
+            x = y;
+            nx = x + 1;
+
+            BUG_ON((x >> 32) != 0);
+            BUG_ON((nx & PGC_count_mask) != 2);
+            y = cmpxchg((u64*)&page->count_info, x, nx);
+        } while (unlikely(y != x));
+    }
+}
+
+static void
 domain_put_page(struct domain* d, unsigned long mpaddr,
                 volatile pte_t* ptep, pte_t old_pte, int clear_PGC_allocate)
 {
@@ -1100,8 +1081,19 @@ domain_put_page(struct domain* d, unsign
             BUG();
         }
 
-       if (clear_PGC_allocate)
-            try_to_clear_PGC_allocate(d, page);
+        if (likely(clear_PGC_allocate)) {
+            if (!test_and_clear_bit(_PGC_allocated, &page->count_info))
+                BUG();
+            /* put_page() is done by domain_page_flush_and_put() */
+        } else {
+            // In this case, page reference count mustn't touched.
+            // domain_page_flush_and_put() decrements it, we increment
+            // it in advence. This patch is slow path.
+            //
+            // guest_remove_page(): owner = d, count_info = 1
+            // memory_exchange(): owner = NULL, count_info = 1
+            adjust_page_count_info(page);
+        }
     }
     domain_page_flush_and_put(d, mpaddr, ptep, old_pte, page);
 }
@@ -1148,7 +1140,7 @@ assign_domain_page_cmpxchg_rel(struct do
 assign_domain_page_cmpxchg_rel(struct domain* d, unsigned long mpaddr,
                                struct page_info* old_page,
                                struct page_info* new_page,
-                               unsigned long flags)
+                               unsigned long flags, int clear_PGC_allocate)
 {
     struct mm_struct *mm = &d->arch.mm;
     volatile pte_t* pte;
@@ -1160,6 +1152,7 @@ assign_domain_page_cmpxchg_rel(struct do
     pte_t new_pte;
     pte_t ret_pte;
 
+    BUG_ON((flags & ASSIGN_pgc_allocated) == 0);
     pte = lookup_alloc_domain_pte(d, mpaddr);
 
  again:
@@ -1200,6 +1193,18 @@ assign_domain_page_cmpxchg_rel(struct do
     BUG_ON(old_mfn == new_mfn);
 
     set_gpfn_from_mfn(old_mfn, INVALID_M2P_ENTRY);
+    if (likely(clear_PGC_allocate)) {
+        if (!test_and_clear_bit(_PGC_allocated, &old_page->count_info))
+            BUG();
+    } else {
+        int ret;
+        // adjust for count_info for domain_page_flush_and_put()
+        // This is slow path.
+        BUG_ON(!test_bit(_PGC_allocated, &old_page->count_info));
+        BUG_ON(d == NULL);
+        ret = get_page(old_page, d);
+        BUG_ON(ret == 0);
+    }
 
     domain_page_flush_and_put(d, mpaddr, pte, old_pte, old_page);
     perfc_incrc(assign_domain_pge_cmpxchg_rel);
@@ -1207,7 +1212,8 @@ assign_domain_page_cmpxchg_rel(struct do
 }
 
 static void
-zap_domain_page_one(struct domain *d, unsigned long mpaddr, unsigned long mfn)
+zap_domain_page_one(struct domain *d, unsigned long mpaddr,
+                    int clear_PGC_allocate, unsigned long mfn)
 {
     struct mm_struct *mm = &d->arch.mm;
     volatile pte_t *pte;
@@ -1258,12 +1264,8 @@ zap_domain_page_one(struct domain *d, un
     page = mfn_to_page(mfn);
     BUG_ON((page->count_info & PGC_count_mask) == 0);
 
-    // exchange_memory() calls
-    //   steal_page()
-    //     page owner is set to NULL
-    //   guest_physmap_remove_page()
-    //     zap_domain_page_one()
-    domain_put_page(d, mpaddr, pte, old_pte, (page_get_owner(page) != NULL));
+    BUG_ON(clear_PGC_allocate && (page_get_owner(page) == NULL));
+    domain_put_page(d, mpaddr, pte, old_pte, clear_PGC_allocate);
     perfc_incrc(zap_dcomain_page_one);
 }
 
@@ -1276,7 +1278,7 @@ dom0vp_zap_physmap(struct domain *d, uns
         return -ENOSYS;
     }
 
-    zap_domain_page_one(d, gpfn << PAGE_SHIFT, INVALID_MFN);
+    zap_domain_page_one(d, gpfn << PAGE_SHIFT, 1, INVALID_MFN);
     perfc_incrc(dom0vp_zap_physmap);
     return 0;
 }
@@ -1563,6 +1565,7 @@ destroy_grant_host_mapping(unsigned long
     /* try_to_clear_PGC_allocate(d, page) is not needed. */
     BUG_ON(page_get_owner(page) == d &&
            get_gpfn_from_mfn(mfn) == gpfn);
+    BUG_ON(pte_pgc_allocated(old_pte));
     domain_page_flush_and_put(d, gpaddr, pte, old_pte, page);
 
     perfc_incrc(destroy_grant_host_mapping);
@@ -1606,9 +1609,6 @@ steal_page(struct domain *d, struct page
         // assign_domain_page_cmpxchg_rel() has release semantics
         // so smp_mb() isn't needed.
 
-        ret = get_page(new, d);
-        BUG_ON(ret == 0);
-
         gpfn = get_gpfn_from_mfn(page_to_mfn(page));
         if (gpfn == INVALID_M2P_ENTRY) {
             free_domheap_page(new);
@@ -1621,7 +1621,7 @@ steal_page(struct domain *d, struct page
 
         ret = assign_domain_page_cmpxchg_rel(d, gpfn << PAGE_SHIFT, page, new,
                                              ASSIGN_writable |
-                                             ASSIGN_pgc_allocated);
+                                             ASSIGN_pgc_allocated, 0);
         if (ret < 0) {
             gdprintk(XENLOG_INFO, "assign_domain_page_cmpxchg_rel failed %d\n",
                     ret);
@@ -1648,18 +1648,8 @@ steal_page(struct domain *d, struct page
         // page->u.inused._domain = 0;
         _nd = x >> 32;
 
-        if (
-            // when !MEMF_no_refcount, page might be put_page()'d or
-            // it will be put_page()'d later depending on queued.
-            unlikely(!(memflags & MEMF_no_refcount) &&
-                     ((x & (PGC_count_mask | PGC_allocated)) !=
+        if (unlikely(((x & (PGC_count_mask | PGC_allocated)) !=
                       (1 | PGC_allocated))) ||
-            // when MEMF_no_refcount, page isn't de-assigned from
-            // this domain yet. So count_info = 2
-            unlikely((memflags & MEMF_no_refcount) &&
-                     ((x & (PGC_count_mask | PGC_allocated)) !=
-                      (2 | PGC_allocated))) ||
-
             unlikely(_nd != _d)) {
             struct domain* nd = unpickle_domptr(_nd);
             if (nd == NULL) {
@@ -1711,11 +1701,8 @@ guest_physmap_add_page(struct domain *d,
 guest_physmap_add_page(struct domain *d, unsigned long gpfn,
                        unsigned long mfn)
 {
-    int ret;
-
     BUG_ON(!mfn_valid(mfn));
-    ret = get_page(mfn_to_page(mfn), d);
-    BUG_ON(ret == 0);
+    BUG_ON(mfn_to_page(mfn)->count_info != (PGC_allocated | 1));
     set_gpfn_from_mfn(mfn, gpfn);
     smp_mb();
     assign_domain_page_replace(d, gpfn << PAGE_SHIFT, mfn,
@@ -1731,7 +1718,7 @@ guest_physmap_remove_page(struct domain 
                           unsigned long mfn)
 {
     BUG_ON(mfn == 0);//XXX
-    zap_domain_page_one(d, gpfn << PAGE_SHIFT, mfn);
+    zap_domain_page_one(d, gpfn << PAGE_SHIFT, 0, mfn);
     perfc_incrc(guest_physmap_remove_page);
 }
 
@@ -2142,26 +2129,8 @@ arch_memory_op(int op, XEN_GUEST_HANDLE(
 
         /* Unmap from old location, if any. */
         gpfn = get_gpfn_from_mfn(mfn);
-        if (gpfn != INVALID_M2P_ENTRY) {
-            /*
-             * guest_physmap_remove_page() (for IPF) descrements page
-             * counter and unset PGC_allocated flag,
-             * so pre-increment page counter and post-set flag inserted
-             */
-            /* pre-increment page counter */
-            if (!get_page(mfn_to_page(mfn), d))
-                goto out;
-
+        if (gpfn != INVALID_M2P_ENTRY)
             guest_physmap_remove_page(d, gpfn, mfn);
-
-            /* post-set PGC_allocated flag */
-            if ((mfn_to_page(mfn)->count_info & PGC_count_mask) != 1) {
-                /* no one but us is using this page */
-                put_page(mfn_to_page(mfn));
-                goto out;
-            }
-            set_bit(_PGC_allocated, &mfn_to_page(mfn)->count_info);
-        }
 
         /* Map at new location. */
         guest_physmap_add_page(d, xatp.gpfn, mfn);
diff -r be1017157768 -r fa77ec03afd6 xen/include/asm-ia64/mm.h
--- a/xen/include/asm-ia64/mm.h Thu Mar 22 09:30:54 2007 -0600
+++ b/xen/include/asm-ia64/mm.h Mon Mar 26 09:15:17 2007 -0600
@@ -212,7 +212,7 @@ static inline int get_page_and_type(stru
 
 static inline int page_is_removable(struct page_info *page)
 {
-    return ((page->count_info & PGC_count_mask) == 2);
+    return ((page->count_info & PGC_count_mask) == 1);
 }
 
 #define        set_machinetophys(_mfn, _pfn) do { } while(0);

_______________________________________________
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] [IA64] Make P2M semantics match x86, Xen patchbot-unstable <=