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

[Xen-changelog] [xen master] xen/arm: support gzip compressed kernels



commit c1be0b102e0e8c558753cb37ee681bf4230fe949
Author:     Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
AuthorDate: Tue Sep 29 16:59:04 2015 +0100
Commit:     Ian Campbell <ian.campbell@xxxxxxxxxx>
CommitDate: Thu Oct 1 12:52:57 2015 +0100

    xen/arm: support gzip compressed kernels
    
    Free the memory used for the compressed kernel and update the relative
    mod->start and mod->size parameters with the uncompressed ones.
    
    To decompress the kernel, allocate memory from dommheap, because freeing
    the modules is done by calling init_heap_pages, which frees to domheap.
    Map these pages using vmap, because they might not be in the linear 1:1
    map.
    
    Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
    CC: ian.campbell@xxxxxxxxxx
    Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
---
 xen/arch/arm/kernel.c       |   88 ++++++++++++++++++++++++++++++++++++++----
 xen/arch/arm/setup.c        |    2 +-
 xen/include/asm-arm/setup.h |    2 +
 3 files changed, 82 insertions(+), 10 deletions(-)

diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index f641b12..61808ac 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -13,6 +13,8 @@
 #include <asm/byteorder.h>
 #include <asm/setup.h>
 #include <xen/libfdt/libfdt.h>
+#include <xen/gunzip.h>
+#include <xen/vmap.h>
 
 #include "kernel.h"
 
@@ -257,6 +259,73 @@ static int kernel_uimage_probe(struct kernel_info *info,
     return 0;
 }
 
+static __init uint32_t output_length(char *image, unsigned long image_len)
+{
+    return *(uint32_t *)&image[image_len - 4];
+}
+
+static __init int kernel_decompress(struct bootmodule *mod)
+{
+    char *output, *input;
+    char magic[2];
+    int rc;
+    unsigned kernel_order_out;
+    paddr_t output_size;
+    struct page_info *pages;
+    mfn_t mfn;
+    int i;
+    paddr_t addr = mod->start;
+    paddr_t size = mod->size;
+
+    if ( size < 2 )
+        return -EINVAL;
+
+    copy_from_paddr(magic, addr, sizeof(magic));
+
+    /* only gzip is supported */
+    if ( !gzip_check(magic, size) )
+        return -EINVAL;
+
+    input = ioremap_cache(addr, size);
+    if ( input == NULL )
+        return -EFAULT;
+
+    output_size = output_length(input, size);
+    kernel_order_out = get_order_from_bytes(output_size);
+    pages = alloc_domheap_pages(NULL, kernel_order_out, 0);
+    if ( pages == NULL )
+    {
+        iounmap(input);
+        return -ENOMEM;
+    }
+    mfn = _mfn(page_to_mfn(pages));
+    output = __vmap(&mfn, 1 << kernel_order_out, 1, 1, PAGE_HYPERVISOR);
+
+    rc = perform_gunzip(output, input, size);
+    clean_dcache_va_range(output, output_size);
+    iounmap(input);
+    vunmap(output);
+
+    mod->start = page_to_maddr(pages);
+    mod->size = output_size;
+
+    /*
+     * Need to free pages after output_size here because they won't be
+     * freed by discard_initial_modules
+     */
+    i = DIV_ROUND_UP(output_size, PAGE_SIZE);
+    for ( ; i < (1 << kernel_order_out); i++ )
+        free_domheap_page(pages + i);
+
+    /*
+     * Free the original kernel, update the pointers to the
+     * decompressed kernel
+     */
+    dt_unreserved_regions(addr, addr + size, init_domheap_pages, 0);
+
+    return 0;
+}
+
 #ifdef CONFIG_ARM_64
 /*
  * Check if the image is a 64-bit Image.
@@ -444,8 +513,6 @@ int kernel_probe(struct kernel_info *info)
     struct bootmodule *mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
     int rc;
 
-    paddr_t start, size;
-
     if ( !mod || !mod->size )
     {
         printk(XENLOG_ERR "Missing kernel boot module?\n");
@@ -453,25 +520,28 @@ int kernel_probe(struct kernel_info *info)
     }
 
     info->kernel_bootmodule = mod;
-    start = mod->start;
-    size = mod->size;
 
-    printk("Loading kernel from boot module @ %"PRIpaddr"\n", start);
+    printk("Loading kernel from boot module @ %"PRIpaddr"\n", mod->start);
 
     info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK);
     if ( info->initrd_bootmodule )
         printk("Loading ramdisk from boot module @ %"PRIpaddr"\n",
                info->initrd_bootmodule->start);
 
+    /* if it is a gzip'ed image, 32bit or 64bit, uncompress it */
+    rc = kernel_decompress(mod);
+    if (rc < 0 && rc != -EINVAL)
+        return rc;
+
 #ifdef CONFIG_ARM_64
-    rc = kernel_zimage64_probe(info, start, size);
+    rc = kernel_zimage64_probe(info, mod->start, mod->size);
     if (rc < 0)
 #endif
-        rc = kernel_uimage_probe(info, start, size);
+        rc = kernel_uimage_probe(info, mod->start, mod->size);
     if (rc < 0)
-        rc = kernel_zimage32_probe(info, start, size);
+        rc = kernel_zimage32_probe(info, mod->start, mod->size);
     if (rc < 0)
-        rc = kernel_elf_probe(info, start, size);
+        rc = kernel_elf_probe(info, mod->start, mod->size);
 
     return rc;
 }
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 48f734f..e95759d 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -165,7 +165,7 @@ static void __init processor_id(void)
     processor_setup();
 }
 
-static void dt_unreserved_regions(paddr_t s, paddr_t e,
+void dt_unreserved_regions(paddr_t s, paddr_t e,
                                   void (*cb)(paddr_t, paddr_t), int first)
 {
     int i, nr = fdt_num_mem_rsv(device_tree_flattened);
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 81bb3da..30ac53b 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -54,6 +54,8 @@ void copy_from_paddr(void *dst, paddr_t paddr, unsigned long 
len);
 int construct_dom0(struct domain *d);
 
 void discard_initial_modules(void);
+void dt_unreserved_regions(paddr_t s, paddr_t e,
+                           void (*cb)(paddr_t, paddr_t), int first);
 
 size_t __init boot_fdt_info(const void *fdt, paddr_t paddr);
 const char __init *boot_fdt_cmdline(const void *fdt);
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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