|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v5 2/2] xen/arm: support gzip compressed kernels
On Tue, 8 Sep 2015, Ian Campbell wrote:
> On Mon, 2015-09-07 at 15:25 +0100, Stefano Stabellini wrote:
> > Free the memory used for the compressed kernel and update the relative
> > mod->start and mod->size parameters with the uncompressed ones.
> >
> > Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
> > Reviewed-by: Julien Grall <julien.grall@xxxxxxxxxx>
> > CC: ian.campbell@xxxxxxxxxx
> >
> > ---
> >
> > Changes in v5:
> > - code style
> >
> > Changes in v4:
> > - return uint32_t from output_length
> > - __init kernel_decompress
> > - code style
> > - add comment
> > - if kernel_decompress fails with error, return
> >
> > Changes in v3:
> > - better error checks in kernel_decompress
> > - free unneeded pages between output_size and kernel_order_out
> > - alloc pages from domheap
> >
> > Changes in v2:
> > - use gzip_check
> > - avoid useless casts
> > - free original kernel image and update the mod with the new address and
> > size
> > - remove changes to common Makefile
> > - remove CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
> > ---
> > xen/arch/arm/kernel.c | 75
> > +++++++++++++++++++++++++++++++++++++++++++
> > xen/arch/arm/setup.c | 2 +-
> > xen/include/asm-arm/setup.h | 2 ++
> > 3 files changed, 78 insertions(+), 1 deletion(-)
> >
> > diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
> > index f641b12..baa5717 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,63 @@ 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 kernel_info *info,
> > + paddr_t *addr, paddr_t *size)
> > +{
> > + char *output, *input, *end;
> > + char magic[2];
> > + int rc;
> > + unsigned kernel_order_out;
> > + paddr_t output_size;
> > + struct page_info *pages;
> > +
> > + 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;
> > + }
> > + output = page_to_virt(pages);
> > +
> > + rc = perform_gunzip(output, input, *size);
> > + clean_dcache_va_range(output, output_size);
> > + iounmap(input);
> > +
> > + *addr = virt_to_maddr(output);
>
> I don't think virt_to_maddr is strictly speaking valid (at the arch
> interface level, our actual implementation may happen to cope) for domheap
> pages, it's only valid for things which are in the linear 1:1 map (~=
> xenheap).
>
> I think you need page_to_maddr(pages) instead.
>
>
> > + *size = output_size;
> > +
> > + end = output + (1 << (kernel_order_out + PAGE_SHIFT));
> > + /*
> > + * Need to free pages after output_size here because they won't be
> > + * freed by discard_initial_modules
> > + */
> > + output += (output_size + PAGE_SIZE - 1) & PAGE_MASK;
> > + for ( ; output < end; output += PAGE_SIZE )
> > + free_domheap_page(virt_to_page(output));
>
> And here again I don't think you can use virt_to_page.
I replaced it all with vmap/vunmap.
> > +
> > + return 0;
> > +}
> > +
> > #ifdef CONFIG_ARM_64
> > /*
> > * Check if the image is a 64-bit Image.
> > @@ -463,6 +522,22 @@ int kernel_probe(struct kernel_info *info)
> > 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(info, &start, &size);
> > + if (rc < 0 && rc != -EINVAL)
>
> IMHO kernel_decompress should return success when the decompress is a nop
> (as represented by EINVAL here) and an error only when the thing needs to
> be decompressed but cannot be.
That mean collapsing the "nothing to do" and the "decompression
successful" cases into a single return value, which I think is not a
good idea. We would be losing information compared to what we have now.
I am quite happy to replace EINVAL with any other return value you think
is most appropriate though.
> That would mean putting the free of the original kernel and the updates of
> mod->* into kernel_decompress. But I think that also makes more sense
> because it confines the "ol' switcheroo" to the one place instead of mostly
> up there and then the tail end cleanup down here. i.e. you call
> kernel_decompress with everything in a consistent and valid state and
> return with everything also in a (possibly different) consistent and valid
> state.
>
> I wouldn't have bothered commenting on this if I weren't already commenting
> on the above, since it's not a huge deal if you think this is the wrong
> direction.
>
> Ian.
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |