@@ -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>
@@ -745,6 +746,8 @@ 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;
+ struct lu_stream lu_stream;
/* Critical region without IDT or TSS. Any fault is deadly! */
@@ -889,9 +892,16 @@ void __init noreturn __start_xen(unsigned long mbi_p)
printk(" Found %d EDD information structures\n",
bootsym(boot_edd_info_nr));
- /* Check that we have at least one Multiboot module. */
if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
- panic("dom0 kernel not specified. Check bootloader configuration\n");
+ {
+ if ( !lu_breadcrumb_phys )
+ panic("dom0 kernel not specified. Check bootloader configuration\n");
+ }
+ else
+ {
+ /* If modules are provided, don't even look for live update data. */
+ lu_breadcrumb_phys = 0;
+ }
/* Check that we don't have a silly number of modules. */
if ( mbi->mods_count > sizeof(module_map) * 8 )
@@ -1337,6 +1347,22 @@ void __init noreturn __start_xen(unsigned long mbi_p)
if ( !xen_phys_start )
panic("Not enough memory to relocate Xen\n");
+ /* Check for the state breadcrumb before giving it to the boot allocator */
+ if ( lu_breadcrumb_phys )
+ {
+ uint64_t *breadcrumb = maddr_to_virt(lu_breadcrumb_phys);
+
+ 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_breadcrumb_phys);
+ }
+ }
+
if ( lu_bootmem_start )
{
if ( !lu_reserved )
@@ -1574,6 +1600,11 @@ void __init noreturn __start_xen(unsigned long mbi_p)
vm_init();
+ if ( lu_breadcrumb_phys )
+ {
+ lu_stream_map(&lu_stream, lu_mfnlist_phys, lu_nr_pages);
+ }
+
if ( lu_bootmem_start )
{
unsigned long limit = virt_to_mfn(HYPERVISOR_VIRT_END - 1);
@@ -124,6 +124,40 @@ void lu_stream_free(struct lu_stream *stream)
}
}
+void lu_stream_map(struct lu_stream *stream, unsigned long mfns_phys, int nr_pages)
+{
+ unsigned int order = get_order_from_bytes((nr_pages + 1) * sizeof(mfn_t));
+ unsigned int i;
+
+ memset(stream, 0, sizeof(*stream));
+
+ stream->len = nr_pages << PAGE_SHIFT;
+ stream->nr_pages = nr_pages;
+ stream->pagelist = __va(mfns_phys);
+
+ map_pages_to_xen((unsigned long)stream->pagelist, maddr_to_mfn(mfns_phys),
+ 1 << order, PAGE_HYPERVISOR);
+
+ /* Reserve the pages used for the pagelist itself. */
+ for ( i = 0; i < (1 << order); i++ )
+ {
+ maddr_to_page(mfns_phys + (i << PAGE_SHIFT))->count_info |= PGC_allocated;
+ }
+
+ /* Validate and reserve the data pages */
+ for ( i = 0; i < nr_pages; i++ )
+ {
+ if (!mfn_valid(stream->pagelist[i]))
+ panic("Invalid MFN %lx in live update stream\n", mfn_x(stream->pagelist[i]));
+
+ mfn_to_page(stream->pagelist[i])->count_info |= PGC_allocated;
+ }
+
+ stream->data = vmap(stream->pagelist, nr_pages);
+ if (!stream->data)
+ panic("Failed to map live update data\n");
+}
+
/*
* local variables:
* mode: c
@@ -22,6 +22,8 @@ void lu_stream_free(struct lu_stream *stream);
struct kexec_image;
int lu_save_all(struct kexec_image *image);
+void lu_stream_map(struct lu_stream *stream, unsigned long mfns_phys, int nr_pages);
+
#endif /* __XEN_LU_H__ */
/*