@@ -25,6 +25,7 @@
#include <xen/nodemask.h>
#include <xen/virtual_region.h>
#include <xen/watchdog.h>
+#include <xen/lu.h>
#include <public/version.h>
#include <compat/platform.h>
#include <compat/xen.h>
@@ -739,6 +740,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
.max_maptrack_frames = -1,
};
const char *hypervisor_name;
+ uint64_t lu_mfnlist_phys = 0, lu_nr_pages = 0;
/* Critical region without IDT or TSS. Any fault is deadly! */
@@ -1336,6 +1338,21 @@ void __init noreturn __start_xen(unsigned long mbi_p)
if ( !xen_phys_start )
panic("Not enough memory to relocate Xen\n");
+ if ( lu_data )
+ {
+ uint64_t *breadcrumb = maddr_to_virt(lu_data);
+
+ lu_mfnlist_phys = breadcrumb[1];
+ lu_nr_pages = breadcrumb[2] >> PAGE_SHIFT;
+
+ if ( breadcrumb[0] == LIVE_UPDATE_MAGIC && lu_nr_pages) {
+ printk("%ld pages of live update data at 0x%lx\n", lu_nr_pages, lu_mfnlist_phys);
+ } else {
+ panic("Live update breadcrumb not found: %lx %lx %lx at %lx\n",
+ breadcrumb[0], breadcrumb[1], breadcrumb[2], lu_data);
+ }
+ }
+
if ( lu_bootmem_start )
{
if ( !lu_reserved )
@@ -1571,6 +1588,9 @@ void __init noreturn __start_xen(unsigned long mbi_p)
numa_initmem_init(0, raw_max_page);
+ if ( lu_data )
+ lu_reserve_pages(lu_mfnlist_phys, lu_nr_pages);
+
if ( lu_bootmem_start )
{
unsigned long limit = virt_to_mfn(HYPERVISOR_VIRT_END - 1);
@@ -1 +1 @@
-obj-y += stream.o save.o
+obj-y += stream.o save.o restore.o
new file mode 100644
@@ -0,0 +1,44 @@
+#include <xen/types.h>
+#include <xen/vmap.h>
+#include <xen/lu.h>
+#include <xen/sched.h>
+
+#define MFNS_PER_PAGE (PAGE_SIZE / sizeof(mfn_t))
+
+/* Returns void. There's not a lot we can do if this fails except panic. */
+void lu_reserve_pages(paddr_t mfns_p, int nr_pages)
+{
+ unsigned int index_pages = (nr_pages + MFNS_PER_PAGE - 1) / MFNS_PER_PAGE;
+ unsigned char *p;
+ mfn_t *mfns;
+ int i;
+
+ /* Would like to vmap(). Too early. */
+ mfns = __va(mfns_p);
+ map_pages_to_xen((unsigned long)mfns, maddr_to_mfn(mfns_p), index_pages, PAGE_HYPERVISOR);
+
+ for ( i = 0; i < index_pages; i++ )
+ {
+ maddr_to_page(mfns_p + (i << PAGE_SHIFT))->count_info |= PGC_allocated;
+ }
+
+ for ( i = 0; i < nr_pages; i++ )
+ {
+ if (!mfn_valid(mfns[i]))
+ panic("Invalid MFN %lx in live update stream\n", mfn_x(mfns[i]));
+
+ mfn_to_page(mfns[i])->count_info |= PGC_allocated;
+ }
+
+ /* XX: Consume the stream of data and mark all domain pages as allocated too. */
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
@@ -13,3 +13,4 @@ void lu_stream_free(struct lu_stream *stream);
struct kexec_image;
int lu_save_all(struct kexec_image *image);
+void lu_reserve_pages(paddr_t mfnlist, int nr_pages);