]> xenbits.xensource.com Git - people/dwmw2/xen.git/commitdiff
Reserve live update memory regions
authorDavid Woodhouse <dwmw@amazon.co.uk>
Thu, 16 Jan 2020 08:51:45 +0000 (09:51 +0100)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Fri, 31 Jan 2020 16:47:09 +0000 (16:47 +0000)
The live update handover requires that a region of memory be reserved
for the new Xen to use in its boot allocator. The original Xen may use
that memory but not for any pages which are mapped to domains, or which
would need to be preserved across the live update for any other reason.

The same constraints apply to initmem pages freed from the Xen image,
since the new Xen will be loaded into the same physical location as the
previous Xen.

There is separate work ongoing which will make the xenheap meet this
requirement by eliminating share_xen_page_with_guest(). For the meantime,
just don't add those pages to the heap at all in the live update case.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
xen/arch/x86/setup.c
xen/common/page_alloc.c
xen/include/xen/mm.h

index c58c6c835e0ec6456ed9bd2e48eaf0efb720a0e1..ae2dcdeb16e0a5460788c66a36c6b4df1eaf516f 100644 (file)
@@ -613,7 +613,7 @@ static void noinline init_done(void)
     }
 
     destroy_xen_mappings(start, end);
-    init_xenheap_pages(__pa(start), __pa(end));
+    init_lu_reserved_pages(__pa(start), __pa(end));
     printk("Freed %lukB init memory\n", (end - start) >> 10);
 
     startup_cpu_idle_loop();
@@ -1520,6 +1520,16 @@ void __init noreturn __start_xen(unsigned long mbi_p)
         unsigned long limit = virt_to_mfn(HYPERVISOR_VIRT_END - 1);
         uint64_t mask = PAGE_SIZE - 1;
 
+        /*
+         * Pages in the reserved LU region must not be used for anything which
+         * will need to persist across a live update. There is ongoing work to
+         * eliminate or limit the use of share_xen_page_with_guest() and get
+         * to a point where we can actually honour that promise, but for now
+         * just *don't* add those pages to the heap. Clear the boot allocator
+         * out completely, before adding the non-reserved ranges.
+         */
+        clear_boot_allocator();
+
         for ( i = 0; i < boot_e820.nr_map; i++ )
         {
             uint64_t s, e;
index 41a23cd84f2d5e5b7fd3ada62443faf48c23d5f2..489548063abb13d59e9fe1293dca577df8e6ea1b 100644 (file)
@@ -1827,6 +1827,51 @@ void __init end_boot_allocator(void)
     printk("\n");
 }
 
+/*
+ * Called when live update is supported. The memory ranges currently
+ * still free in the boot allocator must be added to the reserved
+ * heap, distinct from the xenheap in that pages from it MUST NOT be
+ * used for anything which will be mapped to a domain or otherwise
+ * need to survive a live update.
+ */
+void __init clear_boot_allocator(void)
+{
+    unsigned int i;
+
+    /* Add at least one range on node zero first, if we can. */
+    for ( i = 0; i < nr_bootmem_regions; i++ )
+    {
+        struct bootmem_region *r = &bootmem_region_list[i];
+        if ( (r->s < r->e) &&
+             (phys_to_nid(pfn_to_paddr(r->s)) == cpu_to_node(0)) )
+        {
+            init_lu_reserved_pages(r->s << PAGE_SHIFT, r->e << PAGE_SHIFT);
+            r->e = r->s;
+            break;
+        }
+    }
+    for ( i = nr_bootmem_regions; i-- > 0; )
+    {
+        struct bootmem_region *r = &bootmem_region_list[i];
+        if ( r->s < r->e )
+            init_lu_reserved_pages(r->s << PAGE_SHIFT, r->e << PAGE_SHIFT);
+    }
+    nr_bootmem_regions = 0;
+}
+
+void init_lu_reserved_pages(paddr_t ps, paddr_t pe)
+{
+    if (!lu_bootmem_start)
+        init_xenheap_pages(ps, pe);
+
+    /* There is ongoing work for other reasons to eliminate the use of
+     * share_xen_page_with_guest() and get to a point where the normal
+     * xenheap actually meets the requirement we need for live update
+     * reserved memory, that nothing allocated from it will be mapped
+     * to a guest and/or need to be preserved over a live update.
+     * Until then, we simply don't use these pages after boot. */
+}
+
 static void __init smp_scrub_heap_pages(void *data)
 {
     unsigned long mfn, start, end;
index 24654e8e22647226ee5744166063e8b63e0340a1..4bbd6915057c20fe6d8b960fcf008812fc630b5d 100644 (file)
@@ -153,8 +153,10 @@ struct domain *__must_check page_get_owner_and_reference(struct page_info *);
 void init_boot_pages(paddr_t ps, paddr_t pe);
 mfn_t alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align);
 void end_boot_allocator(void);
+void clear_boot_allocator(void);
 
 /* Xen suballocator. These functions are interrupt-safe. */
+void init_lu_reserved_pages(paddr_t ps, paddr_t pe);
 void init_xenheap_pages(paddr_t ps, paddr_t pe);
 void xenheap_max_mfn(unsigned long mfn);
 void *alloc_xenheap_pages(unsigned int order, unsigned int memflags);