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

[xen staging-4.19] Revert "xen/mm: allow deferred scrub of physmap populate allocated pages"



commit 360813e9e829f0b9439ac08a16808341cf74e993
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Thu Mar 26 11:16:35 2026 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu Mar 26 11:16:58 2026 +0100

    Revert "xen/mm: allow deferred scrub of physmap populate allocated pages"
    
    This reverts commit 52f3b7c6f89abe1f8fd4fc702f150cf3ec1fe89f and its
    prereq 49a4deb467caea989d81f3692ed19a406ef6ee83 ("xen/mm: remove
    aliasing of PGC_need_scrub over PGC_allocated"). Further fixes are
    needed before this can be considered for backporting.
---
 xen/arch/arm/include/asm/mm.h |  10 ++--
 xen/arch/ppc/include/asm/mm.h |  10 ++--
 xen/arch/x86/include/asm/mm.h |  18 +++++---
 xen/common/domain.c           |  25 ----------
 xen/common/memory.c           | 105 +-----------------------------------------
 xen/common/page_alloc.c       |   6 +--
 xen/include/xen/mm.h          |   9 ----
 xen/include/xen/sched.h       |   5 --
 8 files changed, 28 insertions(+), 160 deletions(-)

diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
index ed71cf9bca..48538b5337 100644
--- a/xen/arch/arm/include/asm/mm.h
+++ b/xen/arch/arm/include/asm/mm.h
@@ -145,9 +145,6 @@ struct page_info
 #else
 #define PGC_static     0
 #endif
-/* Page needs to be scrubbed. */
-#define _PGC_need_scrub   PG_shift(5)
-#define PGC_need_scrub    PG_mask(1, 5)
 /* ... */
 /* Page is broken? */
 #define _PGC_broken       PG_shift(7)
@@ -167,6 +164,13 @@ struct page_info
 #define PGC_count_width   PG_shift(10)
 #define PGC_count_mask    ((1UL<<PGC_count_width)-1)
 
+/*
+ * Page needs to be scrubbed. Since this bit can only be set on a page that is
+ * free (i.e. in PGC_state_free) we can reuse PGC_allocated bit.
+ */
+#define _PGC_need_scrub   _PGC_allocated
+#define PGC_need_scrub    PGC_allocated
+
 #ifdef CONFIG_ARM_32
 #define is_xen_heap_page(page) is_xen_heap_mfn(page_to_mfn(page))
 #define is_xen_heap_mfn(mfn) ({                                 \
diff --git a/xen/arch/ppc/include/asm/mm.h b/xen/arch/ppc/include/asm/mm.h
index 9b654945de..a433936076 100644
--- a/xen/arch/ppc/include/asm/mm.h
+++ b/xen/arch/ppc/include/asm/mm.h
@@ -58,9 +58,6 @@ static inline struct page_info *virt_to_page(const void *v)
 /* Page is Xen heap? */
 #define _PGC_xen_heap     PG_shift(2)
 #define PGC_xen_heap      PG_mask(1, 2)
-/* Page needs to be scrubbed. */
-#define _PGC_need_scrub   PG_shift(3)
-#define PGC_need_scrub    PG_mask(1, 3)
 /* Page is broken? */
 #define _PGC_broken       PG_shift(7)
 #define PGC_broken        PG_mask(1, 7)
@@ -79,6 +76,13 @@ static inline struct page_info *virt_to_page(const void *v)
 #define PGC_count_width   PG_shift(10)
 #define PGC_count_mask    ((1UL<<PGC_count_width)-1)
 
+/*
+ * Page needs to be scrubbed. Since this bit can only be set on a page that is
+ * free (i.e. in PGC_state_free) we can reuse PGC_allocated bit.
+ */
+#define _PGC_need_scrub   _PGC_allocated
+#define PGC_need_scrub    PGC_allocated
+
 #define is_xen_heap_page(page) ((page)->count_info & PGC_xen_heap)
 #define is_xen_heap_mfn(mfn) \
     (mfn_valid(mfn) && is_xen_heap_page(mfn_to_page(mfn)))
diff --git a/xen/arch/x86/include/asm/mm.h b/xen/arch/x86/include/asm/mm.h
index 52d2d5ff60..98b66edaca 100644
--- a/xen/arch/x86/include/asm/mm.h
+++ b/xen/arch/x86/include/asm/mm.h
@@ -83,25 +83,29 @@
 #define PGC_state_offlined  PG_mask(2, 6)
 #define PGC_state_free      PG_mask(3, 6)
 #define page_state_is(pg, st) (((pg)->count_info&PGC_state) == PGC_state_##st)
-/* Page needs to be scrubbed. */
-#define _PGC_need_scrub   PG_shift(7)
-#define PGC_need_scrub    PG_mask(1, 7)
 #ifdef CONFIG_SHADOW_PAGING
  /* Set when a page table page has been shadowed. */
-#define _PGC_shadowed_pt  PG_shift(8)
-#define PGC_shadowed_pt   PG_mask(1, 8)
+#define _PGC_shadowed_pt  PG_shift(7)
+#define PGC_shadowed_pt   PG_mask(1, 7)
 #else
 #define PGC_shadowed_pt   0
 #endif
 
 /* Count of references to this frame. */
 #if PGC_shadowed_pt
-#define PGC_count_width   PG_shift(8)
-#else
 #define PGC_count_width   PG_shift(7)
+#else
+#define PGC_count_width   PG_shift(6)
 #endif
 #define PGC_count_mask    ((1UL<<PGC_count_width)-1)
 
+/*
+ * Page needs to be scrubbed. Since this bit can only be set on a page that is
+ * free (i.e. in PGC_state_free) we can reuse PGC_allocated bit.
+ */
+#define _PGC_need_scrub   _PGC_allocated
+#define PGC_need_scrub    PGC_allocated
+
 #ifndef CONFIG_BIGMEM
 /*
  * This definition is solely for the use in struct page_info (and
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 77dacffd22..00c59a9baa 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -392,18 +392,6 @@ static int __init cf_check parse_dom0_param(const char *s)
 }
 custom_param("dom0", parse_dom0_param);
 
-static void domain_pending_scrub_free(struct domain *d)
-{
-    rspin_lock(&d->page_alloc_lock);
-    if ( d->pending_scrub )
-    {
-        FREE_DOMHEAP_PAGES(d->pending_scrub, d->pending_scrub_order);
-        d->pending_scrub_order = 0;
-        d->pending_scrub_index = 0;
-    }
-    rspin_unlock(&d->page_alloc_lock);
-}
-
 /*
  * Release resources held by a domain.  There may or may not be live
  * references to the domain, and it may or may not be fully constructed.
@@ -463,9 +451,6 @@ static int domain_teardown(struct domain *d)
     case PROG_none:
         BUILD_BUG_ON(PROG_none != 0);
 
-        /* Trivial teardown, not long-running enough to need a preemption 
check. */
-        domain_pending_scrub_free(d);
-
     PROGRESS(gnttab_mappings):
         rc = gnttab_release_mappings(d);
         if ( rc )
@@ -508,7 +493,6 @@ static void _domain_destroy(struct domain *d)
 {
     BUG_ON(!d->is_dying);
     BUG_ON(atomic_read(&d->refcnt) != DOMAIN_DESTROYED);
-    ASSERT(!d->pending_scrub);
 
     xfree(d->pbuf);
 
@@ -1436,15 +1420,6 @@ int domain_unpause_by_systemcontroller(struct domain *d)
      */
     if ( new == 0 && !d->creation_finished )
     {
-        if ( d->pending_scrub )
-        {
-            printk(XENLOG_ERR
-                   "%pd: cannot be started with pending unscrubbed pages, 
destroying\n",
-                   d);
-            domain_crash(d);
-            domain_pending_scrub_free(d);
-            return -EBUSY;
-        }
         d->creation_finished = true;
         arch_domain_creation_finished(d);
     }
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 09bb1198bb..9b23cd0bdb 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -155,73 +155,6 @@ static void increase_reservation(struct memop_args *a)
     a->nr_done = i;
 }
 
-/*
- * Temporary storage for a domain assigned page that's not been fully scrubbed.
- * Stored pages must be domheap ones.
- *
- * The stashed page can be freed at any time by Xen, the caller must pass the
- * order and NUMA node requirement to the fetch function to ensure the
- * currently stashed page matches it's requirements.
- */
-static void stash_allocation(struct domain *d, struct page_info *page,
-                             unsigned int order, unsigned int scrub_index)
-{
-    rspin_lock(&d->page_alloc_lock);
-
-    /*
-     * Drop the passed page in preference for the already stashed one.  This
-     * interface is designed to be used for single-threaded domain creation.
-     */
-    if ( d->pending_scrub || d->is_dying )
-        free_domheap_pages(page, order);
-    else
-    {
-        d->pending_scrub_index = scrub_index;
-        d->pending_scrub_order = order;
-        d->pending_scrub = page;
-    }
-
-    rspin_unlock(&d->page_alloc_lock);
-}
-
-static struct page_info *get_stashed_allocation(struct domain *d,
-                                                unsigned int order,
-                                                nodeid_t node,
-                                                unsigned int *scrub_index)
-{
-    struct page_info *page = NULL;
-
-    rspin_lock(&d->page_alloc_lock);
-
-    /*
-     * If there's a pending page to scrub check if it satisfies the current
-     * request.  If it doesn't free it and return NULL.
-     */
-    if ( d->pending_scrub )
-    {
-        if ( d->pending_scrub_order == order &&
-             (node == NUMA_NO_NODE || node == page_to_nid(d->pending_scrub)) )
-        {
-            page = d->pending_scrub;
-            *scrub_index = d->pending_scrub_index;
-        }
-        else
-            free_domheap_pages(d->pending_scrub, d->pending_scrub_order);
-
-        /*
-         * The caller now owns the page or it has been freed, clear stashed
-         * information.  Prevent concurrent usages of get_stashed_allocation()
-         * from returning the same page to different contexts.
-         */
-        d->pending_scrub_index = 0;
-        d->pending_scrub_order = 0;
-        d->pending_scrub = NULL;
-    }
-
-    rspin_unlock(&d->page_alloc_lock);
-    return page;
-}
-
 static void populate_physmap(struct memop_args *a)
 {
     struct page_info *page;
@@ -338,19 +271,7 @@ static void populate_physmap(struct memop_args *a)
             }
             else
             {
-                unsigned int scrub_start = 0;
-                unsigned int memflags =
-                    a->memflags | (d->creation_finished ? 0
-                                                        : MEMF_no_scrub);
-                nodeid_t node =
-                    (a->memflags & MEMF_exact_node) ? 
MEMF_get_node(a->memflags)
-                                                    : NUMA_NO_NODE;
-
-                page = get_stashed_allocation(d, a->extent_order, node,
-                                              &scrub_start);
-
-                if ( !page )
-                    page = alloc_domheap_pages(d, a->extent_order, memflags);
+                page = alloc_domheap_pages(d, a->extent_order, a->memflags);
 
                 if ( unlikely(!page) )
                 {
@@ -361,30 +282,6 @@ static void populate_physmap(struct memop_args *a)
                     goto out;
                 }
 
-                if ( memflags & MEMF_no_scrub )
-                {
-                    unsigned int dirty_cnt = 0;
-
-                    /* Check if there's anything to scrub. */
-                    for ( j = scrub_start; j < (1U << a->extent_order); j++ )
-                    {
-                        if ( !test_and_clear_bit(_PGC_need_scrub,
-                                                 &page[j].count_info) )
-                            continue;
-
-                        scrub_one_page(&page[j]);
-
-                        if ( (j + 1) != (1U << a->extent_order) &&
-                             !(++dirty_cnt & 0xff) &&
-                             hypercall_preempt_check() )
-                        {
-                            a->preempted = 1;
-                            stash_allocation(d, page, a->extent_order, j + 1);
-                            goto out;
-                        }
-                    }
-                }
-
                 if ( unlikely(a->memflags & MEMF_no_tlbflush) )
                 {
                     for ( j = 0; j < (1U << a->extent_order); j++ )
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 4304c3dbd4..bbb8578459 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -2364,8 +2364,7 @@ int assign_pages(
 
         for ( i = 0; i < nr; i++ )
         {
-            ASSERT(!(pg[i].count_info &
-                     ~(PGC_extra | PGC_static | PGC_need_scrub)));
+            ASSERT(!(pg[i].count_info & ~(PGC_extra | PGC_static)));
             if ( pg[i].count_info & PGC_extra )
                 extra_pages++;
         }
@@ -2425,8 +2424,7 @@ int assign_pages(
         page_set_owner(&pg[i], d);
         smp_wmb(); /* Domain pointer must be visible before updating refcnt. */
         pg[i].count_info =
-            (pg[i].count_info & (PGC_extra | PGC_static | PGC_need_scrub)) |
-            PGC_allocated | 1;
+            (pg[i].count_info & (PGC_extra | PGC_static)) | PGC_allocated | 1;
 
         page_list_add_tail(&pg[i], page_to_list(d, &pg[i]));
     }
diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h
index fe32ef81cb..7561297a75 100644
--- a/xen/include/xen/mm.h
+++ b/xen/include/xen/mm.h
@@ -142,15 +142,6 @@ unsigned long avail_domheap_pages(void);
 unsigned long avail_node_heap_pages(unsigned int nodeid);
 #define alloc_domheap_page(d,f) (alloc_domheap_pages(d,0,f))
 #define free_domheap_page(p)  (free_domheap_pages(p,0))
-
-/* Free an allocation, and zero the pointer to it. */
-#define FREE_DOMHEAP_PAGES(p, o) do { \
-    void *_ptr_ = (p);                \
-    (p) = NULL;                       \
-    free_domheap_pages(_ptr_, o);     \
-} while ( false )
-#define FREE_DOMHEAP_PAGE(p) FREE_DOMHEAP_PAGES(p, 0)
-
 unsigned int online_page(mfn_t mfn, uint32_t *status);
 int offline_page(mfn_t mfn, int broken, uint32_t *status);
 int query_page_offline(mfn_t mfn, uint32_t *status);
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index ff831c7254..2a83b9dacf 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -636,11 +636,6 @@ struct domain
     } ioreq_server;
 #endif
 
-    /* Pointer to allocated domheap page that possibly needs scrubbing. */
-    struct page_info *pending_scrub;
-    unsigned int pending_scrub_order;
-    unsigned int pending_scrub_index;
-
     /* Holding CDF_* constant. Internal flags for domain creation. */
     unsigned int cdf;
 };
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.19



 


Rackspace

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