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

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



commit 73f4c7aab763cd1cfbcd778ad309fe2c2991cb43
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Thu Mar 26 11:03:11 2026 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu Mar 26 11:04:14 2026 +0100

    Revert "xen/mm: allow deferred scrub of physmap populate allocated pages"
    
    This reverts commit 6228ea8acddadbd815f958fb1a867f54c01ddf78 and its
    prereq 15cd2b8f1bac5f4adf0f8303ae79298a612b53e1 ("xen/mm: remove
    aliasing of PGC_need_scrub over PGC_allocated"). Further fixes are
    needed before these can be considered for backporting.
---
 xen/arch/arm/include/asm/mm.h   |  10 ++--
 xen/arch/ppc/include/asm/mm.h   |  10 ++--
 xen/arch/riscv/include/asm/mm.h |  10 ++--
 xen/arch/x86/include/asm/mm.h   |  18 ++++---
 xen/common/domain.c             |  23 ---------
 xen/common/memory.c             | 105 +---------------------------------------
 xen/common/page_alloc.c         |   4 +-
 xen/include/xen/mm.h            |  10 ----
 xen/include/xen/sched.h         |   5 --
 9 files changed, 35 insertions(+), 160 deletions(-)

diff --git a/xen/arch/arm/include/asm/mm.h b/xen/arch/arm/include/asm/mm.h
index ee1f60c59e..7a93dad2ed 100644
--- a/xen/arch/arm/include/asm/mm.h
+++ b/xen/arch/arm/include/asm/mm.h
@@ -144,9 +144,6 @@ struct page_info
 #define _PGC_colored      PG_shift(4)
 #define PGC_colored       PG_mask(1, 4)
 #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)
@@ -166,6 +163,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
+
 #if defined(CONFIG_ARM_64) || defined(CONFIG_MPU)
 #define is_xen_heap_page(page) ((page)->count_info & PGC_xen_heap)
 #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 82a9551082..a33eeec43b 100644
--- a/xen/arch/ppc/include/asm/mm.h
+++ b/xen/arch/ppc/include/asm/mm.h
@@ -57,9 +57,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)
@@ -78,6 +75,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/riscv/include/asm/mm.h b/xen/arch/riscv/include/asm/mm.h
index 4c37d87508..9283616c02 100644
--- a/xen/arch/riscv/include/asm/mm.h
+++ b/xen/arch/riscv/include/asm/mm.h
@@ -247,15 +247,19 @@ static inline bool arch_mfns_in_directmap(unsigned long 
mfn, unsigned long nr)
 #define PGT_count_width   PG_shift(2)
 #define PGT_count_mask    ((1UL << PGT_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
+
 /* Cleared when the owning guest 'frees' this page. */
 #define _PGC_allocated    PG_shift(1)
 #define PGC_allocated     PG_mask(1, 1)
 /* 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(4)
-#define PGC_need_scrub    PG_mask(1, 4)
 /* Page is broken? */
 #define _PGC_broken       PG_shift(7)
 #define PGC_broken        PG_mask(1, 7)
diff --git a/xen/arch/x86/include/asm/mm.h b/xen/arch/x86/include/asm/mm.h
index d35086e31e..08153e6d6f 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 75c7da16e2..88db82d187 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -582,18 +582,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.
@@ -655,7 +643,6 @@ static int domain_teardown(struct domain *d)
 
         /* Trivial teardown, not long-running enough to need a preemption 
check. */
         domain_llc_coloring_free(d);
-        domain_pending_scrub_free(d);
 
     PROGRESS(gnttab_mappings):
         rc = gnttab_release_mappings(d);
@@ -699,7 +686,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);
 
@@ -1665,15 +1651,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 9240a6005e..10becf7c1f 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -159,73 +159,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;
@@ -342,19 +275,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) )
                 {
@@ -365,30 +286,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], true);
-
-                        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 588b5b99cb..2efc11ce09 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -170,7 +170,7 @@
 /*
  * Flags that are preserved in assign_pages() (and only there)
  */
-#define PGC_preserved (PGC_extra | PGC_static | PGC_colored | PGC_need_scrub)
+#define PGC_preserved (PGC_extra | PGC_static | PGC_colored)
 
 #ifndef PGT_TYPE_INFO_INITIALIZER
 #define PGT_TYPE_INFO_INITIALIZER 0
@@ -792,7 +792,7 @@ static void page_list_add_scrub(struct page_info *pg, 
unsigned int node,
 # define scrub_page_cold clear_page_cold
 #endif
 
-void scrub_one_page(const struct page_info *pg, bool cold)
+static void scrub_one_page(const struct page_info *pg, bool cold)
 {
     void *ptr;
 
diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h
index 49c34248f9..b968f47b87 100644
--- a/xen/include/xen/mm.h
+++ b/xen/include/xen/mm.h
@@ -145,16 +145,6 @@ 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)
-
-void scrub_one_page(const struct page_info *pg, bool cold);
-
 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 c89b930cbd..610f3d4c0d 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -662,11 +662,6 @@ struct domain
         /* Permission to take ownership of the physical console input. */
         bool input_allowed;
     } console;
-
-    /* Pointer to allocated domheap page that possibly needs scrubbing. */
-    struct page_info *pending_scrub;
-    unsigned int pending_scrub_order;
-    unsigned int pending_scrub_index;
 } __aligned(PAGE_SIZE);
 
 static inline struct page_list_head *page_to_list(
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.21



 


Rackspace

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