* [PATCH 0/2] support compressed kernels on ARM64
@ 2015-08-12 14:47 Stefano Stabellini
2015-08-12 14:47 ` [PATCH 1/2] xen: move perform_gunzip to common Stefano Stabellini
2015-08-12 14:47 ` [PATCH 2/2] xen/arm: support compressed kernels Stefano Stabellini
0 siblings, 2 replies; 20+ messages in thread
From: Stefano Stabellini @ 2015-08-12 14:47 UTC (permalink / raw)
To: xen-devel; +Cc: Ian Campbell, Stefano Stabellini
Hi all,
this patch series introduces support for compressed kernels, such as
the standard Image.gz format used by Linux on arm64 by default, in Xen.
Without it, Xen cannot load the default kernel shipped by distros, such
as CentOS 7.
Stefano Stabellini (2):
xen: move perform_gunzip to common
xen/arm: support compressed kernels
xen/arch/arm/kernel.c | 36 ++++++++++
xen/arch/x86/bzimage.c | 142 +--------------------------------------
xen/common/Makefile | 2 +-
xen/common/decompress.c | 2 +
xen/common/gunzip.c | 141 ++++++++++++++++++++++++++++++++++++++
xen/include/asm-arm/byteorder.h | 2 +
xen/include/xen/decompress.h | 11 ++-
7 files changed, 193 insertions(+), 143 deletions(-)
create mode 100644 xen/common/gunzip.c
Cheers,
Stefano
^ permalink raw reply [flat|nested] 20+ messages in thread* [PATCH 1/2] xen: move perform_gunzip to common 2015-08-12 14:47 [PATCH 0/2] support compressed kernels on ARM64 Stefano Stabellini @ 2015-08-12 14:47 ` Stefano Stabellini 2015-08-12 15:14 ` Jan Beulich 2015-08-12 14:47 ` [PATCH 2/2] xen/arm: support compressed kernels Stefano Stabellini 1 sibling, 1 reply; 20+ messages in thread From: Stefano Stabellini @ 2015-08-12 14:47 UTC (permalink / raw) To: xen-devel; +Cc: andrew.cooper3, Ian.Campbell, JBeulich, Stefano Stabellini The current gunzip code to uncompress the Dom0 kernel is implemented in inflate.c which is included by bzimage.c. I am looking to doing the same on ARM64 but there is quite a bit of boilerplate definitions that I would need to import in order for inflate.c to work correctly. Instead of copying/pasting the code from x86/bzimage.c, move those definitions to a new common file, gunzip.c and integrate the gunzip uncompressing route into the decompress function. Only support the simplest calling case (which actually is the only one in use), return -EOPNOTSUPP if the fill or flush functions are passed as arguments. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> CC: JBeulich@suse.com CC: andrew.cooper3@citrix.com --- xen/arch/x86/bzimage.c | 142 +----------------------------------------- xen/common/Makefile | 2 +- xen/common/decompress.c | 2 + xen/common/gunzip.c | 141 +++++++++++++++++++++++++++++++++++++++++ xen/include/xen/decompress.h | 11 +++- 5 files changed, 155 insertions(+), 143 deletions(-) create mode 100644 xen/common/gunzip.c diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c index c86c39e..976225c 100644 --- a/xen/arch/x86/bzimage.c +++ b/xen/arch/x86/bzimage.c @@ -8,144 +8,6 @@ #include <xen/libelf.h> #include <asm/bzimage.h> -#define HEAPORDER 3 - -static unsigned char *__initdata window; -#define memptr long -static memptr __initdata free_mem_ptr; -static memptr __initdata free_mem_end_ptr; - -#define WSIZE 0x80000000 - -static unsigned char *__initdata inbuf; -static unsigned __initdata insize; - -/* Index of next byte to be processed in inbuf: */ -static unsigned __initdata inptr; - -/* Bytes in output buffer: */ -static unsigned __initdata outcnt; - -#define OF(args) args -#define STATIC static - -#define memzero(s, n) memset((s), 0, (n)) - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define INIT __init -#define INITDATA __initdata - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0) -# define Trace(x) do { fprintf x; } while (0) -# define Tracev(x) do { if (verbose) fprintf x ; } while (0) -# define Tracevv(x) do { if (verbose > 1) fprintf x ; } while (0) -# define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0) -# define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0) -#else -# define Assert(cond, msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c, x) -# define Tracecv(c, x) -#endif - -static long __initdata bytes_out; -static void flush_window(void); - -static __init void error(char *x) -{ - panic("%s", x); -} - -static __init int fill_inbuf(void) -{ - error("ran out of input data"); - return 0; -} - - -#include "../../common/inflate.c" - -static __init void flush_window(void) -{ - /* - * The window is equal to the output buffer therefore only need to - * compute the crc. - */ - unsigned long c = crc; - unsigned n; - unsigned char *in, ch; - - in = window; - for ( n = 0; n < outcnt; n++ ) - { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - - bytes_out += (unsigned long)outcnt; - outcnt = 0; -} - -static __init unsigned long output_length(char *image, unsigned long image_len) -{ - return *(uint32_t *)&image[image_len - 4]; -} - -static __init int gzip_check(char *image, unsigned long image_len) -{ - unsigned char magic0, magic1; - - if ( image_len < 2 ) - return 0; - - magic0 = (unsigned char)image[0]; - magic1 = (unsigned char)image[1]; - - return (magic0 == 0x1f) && ((magic1 == 0x8b) || (magic1 == 0x9e)); -} - -static __init int perform_gunzip(char *output, char *image, unsigned long image_len) -{ - int rc; - - if ( !gzip_check(image, image_len) ) - return 1; - - window = (unsigned char *)output; - - free_mem_ptr = (unsigned long)alloc_xenheap_pages(HEAPORDER, 0); - free_mem_end_ptr = free_mem_ptr + (PAGE_SIZE << HEAPORDER); - - inbuf = (unsigned char *)image; - insize = image_len; - inptr = 0; - - makecrc(); - - if ( gunzip() < 0 ) - { - rc = -EINVAL; - } - else - { - rc = 0; - } - - free_xenheap_pages((void *)free_mem_ptr, HEAPORDER); - - return rc; -} - struct __packed setup_header { uint8_t _pad0[0x1f1]; /* skip uninteresting stuff */ uint8_t setup_sects; @@ -258,9 +120,7 @@ int __init bzimage_parse(char *image_base, char **image_start, unsigned long *im output_len = output_length(*image_start, orig_image_len); - if ( (err = perform_gunzip(image_base, *image_start, orig_image_len)) > 0 ) - err = decompress(*image_start, orig_image_len, image_base); - + err = decompress(*image_start, orig_image_len, image_base); if ( !err ) { *image_start = image_base; diff --git a/xen/common/Makefile b/xen/common/Makefile index 3fdf931..0a4d4fa 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -56,7 +56,7 @@ obj-y += vsprintf.o obj-y += wait.o obj-y += xmalloc_tlsf.o -obj-bin-$(CONFIG_X86) += $(foreach n,decompress bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) +obj-bin-$(CONFIG_X86) += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) obj-$(perfc) += perfc.o obj-$(crash_debug) += gdbstub.o diff --git a/xen/common/decompress.c b/xen/common/decompress.c index 5f86af9..67b48ec 100644 --- a/xen/common/decompress.c +++ b/xen/common/decompress.c @@ -16,6 +16,8 @@ int __init decompress(void *inbuf, unsigned int len, void *outbuf) (!memcmp(inbuf, "\037\213", 2) || !memcmp(inbuf, "\037\236", 2)) ) return gunzip(inbuf, len, NULL, NULL, outbuf, NULL, error); #endif + if (gzip_check(inbuf, len)) + return perform_gunzip(inbuf, len, NULL, NULL, outbuf, NULL, error); if ( len >= 3 && !memcmp(inbuf, "\x42\x5a\x68", 3) ) return bunzip2(inbuf, len, NULL, NULL, outbuf, NULL, error); diff --git a/xen/common/gunzip.c b/xen/common/gunzip.c new file mode 100644 index 0000000..cb3e0c6 --- /dev/null +++ b/xen/common/gunzip.c @@ -0,0 +1,141 @@ +#include <xen/config.h> +#include <xen/errno.h> +#include <xen/init.h> +#include <xen/lib.h> +#include <xen/mm.h> + +#define HEAPORDER 3 + +static unsigned char *__initdata window; +#define memptr long +static memptr __initdata free_mem_ptr; +static memptr __initdata free_mem_end_ptr; + +#define WSIZE 0x80000000 + +static unsigned char *__initdata inbuf; +static unsigned __initdata insize; + +/* Index of next byte to be processed in inbuf: */ +static unsigned __initdata inptr; + +/* Bytes in output buffer: */ +static unsigned __initdata outcnt; + +#define OF(args) args +#define STATIC static + +#define memzero(s, n) memset((s), 0, (n)) + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define INIT __init +#define INITDATA __initdata + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0) +# define Trace(x) do { fprintf x; } while (0) +# define Tracev(x) do { if (verbose) fprintf x ; } while (0) +# define Tracevv(x) do { if (verbose > 1) fprintf x ; } while (0) +# define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0) +# define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0) +#else +# define Assert(cond, msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c, x) +# define Tracecv(c, x) +#endif + +static long __initdata bytes_out; +static void flush_window(void); + +static __initdata void (*error)(const char *x); + +static __init int fill_inbuf(void) +{ + error("ran out of input data"); + return 0; +} + +#include "inflate.c" + +static INIT void flush_window(void) +{ + /* + * The window is equal to the output buffer therefore only need to + * compute the crc. + */ + unsigned long c = crc; + unsigned n; + unsigned char *in, ch; + + in = window; + for ( n = 0; n < outcnt; n++ ) + { + ch = *in++; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + + bytes_out += (unsigned long)outcnt; + outcnt = 0; +} + +int INIT gzip_check(char *image, unsigned long image_len) +{ + unsigned char magic0, magic1; + + if ( image_len < 2 ) + return 0; + + magic0 = (unsigned char)image[0]; + magic1 = (unsigned char)image[1]; + + return (magic0 == 0x1f) && ((magic1 == 0x8b) || (magic1 == 0x9e)); +} + +int INIT perform_gunzip(unsigned char *image, unsigned int image_len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + unsigned int *pos, + void(*error_fn)(const char *x)) +{ + int rc; + + /* currently not supported */ + if (fill != NULL || flush != NULL) + return -EOPNOTSUPP; + + error = error_fn; + window = (unsigned char *)output; + + free_mem_ptr = (unsigned long)alloc_xenheap_pages(HEAPORDER, 0); + free_mem_end_ptr = free_mem_ptr + (PAGE_SIZE << HEAPORDER); + + inbuf = (unsigned char *)image; + insize = image_len; + inptr = 0; + + makecrc(); + + if ( gunzip() < 0 ) + { + rc = -EINVAL; + } + else + { + rc = 0; + } + + free_xenheap_pages((void *)free_mem_ptr, HEAPORDER); + + return rc; +} diff --git a/xen/include/xen/decompress.h b/xen/include/xen/decompress.h index b2955fa..248f0fb 100644 --- a/xen/include/xen/decompress.h +++ b/xen/include/xen/decompress.h @@ -1,6 +1,8 @@ #ifndef __XEN_GENERIC_H #define __XEN_GENERIC_H +#include <xen/types.h> + typedef int decompress_fn(unsigned char *inbuf, unsigned int len, int (*fill)(void*, unsigned int), int (*flush)(void*, unsigned int), @@ -31,8 +33,15 @@ typedef int decompress_fn(unsigned char *inbuf, unsigned int len, * dependent). */ -decompress_fn bunzip2, unxz, unlzma, unlzo, unlz4; +decompress_fn perform_gunzip, bunzip2, unxz, unlzma, unlzo, unlz4; int decompress(void *inbuf, unsigned int len, void *outbuf); +static inline unsigned long output_length(char *image, unsigned long image_len) +{ + return *(uint32_t *)&image[image_len - 4]; +} +int gzip_check(char *image, unsigned long image_len); + + #endif -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] xen: move perform_gunzip to common 2015-08-12 14:47 ` [PATCH 1/2] xen: move perform_gunzip to common Stefano Stabellini @ 2015-08-12 15:14 ` Jan Beulich 2015-08-12 16:15 ` Stefano Stabellini 0 siblings, 1 reply; 20+ messages in thread From: Jan Beulich @ 2015-08-12 15:14 UTC (permalink / raw) To: StefanoStabellini; +Cc: andrew.cooper3, Ian.Campbell, xen-devel >>> On 12.08.15 at 16:47, <stefano.stabellini@eu.citrix.com> wrote: > --- a/xen/common/decompress.c > +++ b/xen/common/decompress.c > @@ -16,6 +16,8 @@ int __init decompress(void *inbuf, unsigned int len, void *outbuf) > (!memcmp(inbuf, "\037\213", 2) || !memcmp(inbuf, "\037\236", 2)) ) > return gunzip(inbuf, len, NULL, NULL, outbuf, NULL, error); > #endif > + if (gzip_check(inbuf, len)) > + return perform_gunzip(inbuf, len, NULL, NULL, outbuf, NULL, error); Afaict it would be appropriate for this to replace the #if 0 block the end of which is seen here as context. > @@ -31,8 +33,15 @@ typedef int decompress_fn(unsigned char *inbuf, unsigned int len, > * dependent). > */ > > -decompress_fn bunzip2, unxz, unlzma, unlzo, unlz4; > +decompress_fn perform_gunzip, bunzip2, unxz, unlzma, unlzo, unlz4; > > int decompress(void *inbuf, unsigned int len, void *outbuf); > > +static inline unsigned long output_length(char *image, unsigned long image_len) Neither of the callers gets moved out of bzimage.c - why does this function need to move? And if it's unavoidable I'd suggest naming it with a meaningful prefix and using the opportunity to constify the first parameter. And while unlikely for it to not get inlined, retaining the original __init would seem necessary to avoid build failures which would result if this didn't get inlined. Jan ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] xen: move perform_gunzip to common 2015-08-12 15:14 ` Jan Beulich @ 2015-08-12 16:15 ` Stefano Stabellini 2015-08-13 6:29 ` Jan Beulich 0 siblings, 1 reply; 20+ messages in thread From: Stefano Stabellini @ 2015-08-12 16:15 UTC (permalink / raw) To: Jan Beulich; +Cc: andrew.cooper3, xen-devel, Ian.Campbell, StefanoStabellini On Wed, 12 Aug 2015, Jan Beulich wrote: > >>> On 12.08.15 at 16:47, <stefano.stabellini@eu.citrix.com> wrote: > > --- a/xen/common/decompress.c > > +++ b/xen/common/decompress.c > > @@ -16,6 +16,8 @@ int __init decompress(void *inbuf, unsigned int len, void *outbuf) > > (!memcmp(inbuf, "\037\213", 2) || !memcmp(inbuf, "\037\236", 2)) ) > > return gunzip(inbuf, len, NULL, NULL, outbuf, NULL, error); > > #endif > > + if (gzip_check(inbuf, len)) > > + return perform_gunzip(inbuf, len, NULL, NULL, outbuf, NULL, error); > > Afaict it would be appropriate for this to replace the #if 0 block the > end of which is seen here as context. Yes, I'll make the change. > > @@ -31,8 +33,15 @@ typedef int decompress_fn(unsigned char *inbuf, unsigned int len, > > * dependent). > > */ > > > > -decompress_fn bunzip2, unxz, unlzma, unlzo, unlz4; > > +decompress_fn perform_gunzip, bunzip2, unxz, unlzma, unlzo, unlz4; > > > > int decompress(void *inbuf, unsigned int len, void *outbuf); > > > > +static inline unsigned long output_length(char *image, unsigned long image_len) > > Neither of the callers gets moved out of bzimage.c - why does this > function need to move? We'll use it on arm. > And if it's unavoidable I'd suggest naming it > with a meaningful prefix and using the opportunity to constify the > first parameter. And while unlikely for it to not get inlined, retaining > the original __init would seem necessary to avoid build failures which > would result if this didn't get inlined. I'll do. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] xen: move perform_gunzip to common 2015-08-12 16:15 ` Stefano Stabellini @ 2015-08-13 6:29 ` Jan Beulich 2015-08-13 9:28 ` Stefano Stabellini 0 siblings, 1 reply; 20+ messages in thread From: Jan Beulich @ 2015-08-13 6:29 UTC (permalink / raw) To: StefanoStabellini; +Cc: andrew.cooper3, Ian.Campbell, xen-devel >>> On 12.08.15 at 18:15, <stefano.stabellini@eu.citrix.com> wrote: > On Wed, 12 Aug 2015, Jan Beulich wrote: >> >>> On 12.08.15 at 16:47, <stefano.stabellini@eu.citrix.com> wrote: >> > @@ -31,8 +33,15 @@ typedef int decompress_fn(unsigned char *inbuf, unsigned int len, >> > * dependent). >> > */ >> > >> > -decompress_fn bunzip2, unxz, unlzma, unlzo, unlz4; >> > +decompress_fn perform_gunzip, bunzip2, unxz, unlzma, unlzo, unlz4; >> > >> > int decompress(void *inbuf, unsigned int len, void *outbuf); >> > >> > +static inline unsigned long output_length(char *image, unsigned long image_len) >> >> Neither of the callers gets moved out of bzimage.c - why does this >> function need to move? > > We'll use it on arm. Hmm, the way it is used on x86 makes it quite architecture specific (namely because of the assumption that the size is also in said place for non-gz compression methods). I'd therefore prefer code duplication over code sharing here. Jan ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] xen: move perform_gunzip to common 2015-08-13 6:29 ` Jan Beulich @ 2015-08-13 9:28 ` Stefano Stabellini 2015-08-13 9:57 ` Jan Beulich 0 siblings, 1 reply; 20+ messages in thread From: Stefano Stabellini @ 2015-08-13 9:28 UTC (permalink / raw) To: Jan Beulich; +Cc: andrew.cooper3, xen-devel, Ian.Campbell, StefanoStabellini On Thu, 13 Aug 2015, Jan Beulich wrote: > >>> On 12.08.15 at 18:15, <stefano.stabellini@eu.citrix.com> wrote: > > On Wed, 12 Aug 2015, Jan Beulich wrote: > >> >>> On 12.08.15 at 16:47, <stefano.stabellini@eu.citrix.com> wrote: > >> > @@ -31,8 +33,15 @@ typedef int decompress_fn(unsigned char *inbuf, unsigned int len, > >> > * dependent). > >> > */ > >> > > >> > -decompress_fn bunzip2, unxz, unlzma, unlzo, unlz4; > >> > +decompress_fn perform_gunzip, bunzip2, unxz, unlzma, unlzo, unlz4; > >> > > >> > int decompress(void *inbuf, unsigned int len, void *outbuf); > >> > > >> > +static inline unsigned long output_length(char *image, unsigned long image_len) > >> > >> Neither of the callers gets moved out of bzimage.c - why does this > >> function need to move? > > > > We'll use it on arm. > > Hmm, the way it is used on x86 makes it quite architecture specific > (namely because of the assumption that the size is also in said > place for non-gz compression methods). I'd therefore prefer code > duplication over code sharing here. Actually after seeing the size and quality of the resulting patches, I am starting to feel the same way. In terms of code changes, I was thinking that the best result would be moving the "boilerplate" code from xen/arch/x86/bzimage.c to xen/common/inflate.c, see below, then the interface would become just perform_gunzip and gzip_check. But I guess you wouldn't want inflate.c to be modified, right? Alternatively we could move it to a new file, let's call it gunzip.h, that would #include "inflate.c", so: bzimage.c -- #include --> gunzip.h -- #include --> inflate.c And again we just leave the perform_gunzip and gzip_check calls in bzimage.c. What do you think? --- diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c index c86c39e..cfd34d6 100644 --- a/xen/arch/x86/bzimage.c +++ b/xen/arch/x86/bzimage.c @@ -8,144 +8,8 @@ #include <xen/libelf.h> #include <asm/bzimage.h> -#define HEAPORDER 3 - -static unsigned char *__initdata window; -#define memptr long -static memptr __initdata free_mem_ptr; -static memptr __initdata free_mem_end_ptr; - -#define WSIZE 0x80000000 - -static unsigned char *__initdata inbuf; -static unsigned __initdata insize; - -/* Index of next byte to be processed in inbuf: */ -static unsigned __initdata inptr; - -/* Bytes in output buffer: */ -static unsigned __initdata outcnt; - -#define OF(args) args -#define STATIC static - -#define memzero(s, n) memset((s), 0, (n)) - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define INIT __init -#define INITDATA __initdata - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0) -# define Trace(x) do { fprintf x; } while (0) -# define Tracev(x) do { if (verbose) fprintf x ; } while (0) -# define Tracevv(x) do { if (verbose > 1) fprintf x ; } while (0) -# define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0) -# define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0) -#else -# define Assert(cond, msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c, x) -# define Tracecv(c, x) -#endif - -static long __initdata bytes_out; -static void flush_window(void); - -static __init void error(char *x) -{ - panic("%s", x); -} - -static __init int fill_inbuf(void) -{ - error("ran out of input data"); - return 0; -} - - #include "../../common/inflate.c" -static __init void flush_window(void) -{ - /* - * The window is equal to the output buffer therefore only need to - * compute the crc. - */ - unsigned long c = crc; - unsigned n; - unsigned char *in, ch; - - in = window; - for ( n = 0; n < outcnt; n++ ) - { - ch = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - - bytes_out += (unsigned long)outcnt; - outcnt = 0; -} - -static __init unsigned long output_length(char *image, unsigned long image_len) -{ - return *(uint32_t *)&image[image_len - 4]; -} - -static __init int gzip_check(char *image, unsigned long image_len) -{ - unsigned char magic0, magic1; - - if ( image_len < 2 ) - return 0; - - magic0 = (unsigned char)image[0]; - magic1 = (unsigned char)image[1]; - - return (magic0 == 0x1f) && ((magic1 == 0x8b) || (magic1 == 0x9e)); -} - -static __init int perform_gunzip(char *output, char *image, unsigned long image_len) -{ - int rc; - - if ( !gzip_check(image, image_len) ) - return 1; - - window = (unsigned char *)output; - - free_mem_ptr = (unsigned long)alloc_xenheap_pages(HEAPORDER, 0); - free_mem_end_ptr = free_mem_ptr + (PAGE_SIZE << HEAPORDER); - - inbuf = (unsigned char *)image; - insize = image_len; - inptr = 0; - - makecrc(); - - if ( gunzip() < 0 ) - { - rc = -EINVAL; - } - else - { - rc = 0; - } - - free_xenheap_pages((void *)free_mem_ptr, HEAPORDER); - - return rc; -} - struct __packed setup_header { uint8_t _pad0[0x1f1]; /* skip uninteresting stuff */ uint8_t setup_sects; diff --git a/xen/common/inflate.c b/xen/common/inflate.c index f99c985..10c236a 100644 --- a/xen/common/inflate.c +++ b/xen/common/inflate.c @@ -103,6 +103,68 @@ the two sets of lengths. */ +#define HEAPORDER 3 + +static unsigned char *__initdata window; +#define memptr long +static memptr __initdata free_mem_ptr; +static memptr __initdata free_mem_end_ptr; + +#define WSIZE 0x80000000 + +static unsigned char *__initdata inbuf; +static unsigned __initdata insize; + +/* Index of next byte to be processed in inbuf: */ +static unsigned __initdata inptr; + +/* Bytes in output buffer: */ +static unsigned __initdata outcnt; + +#define OF(args) args +#define STATIC static + +#define memzero(s, n) memset((s), 0, (n)) + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define INIT __init +#define INITDATA __initdata + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +#ifdef DEBUG +# define Assert(cond, msg) do { if (!(cond)) error(msg); } while (0) +# define Trace(x) do { fprintf x; } while (0) +# define Tracev(x) do { if (verbose) fprintf x ; } while (0) +# define Tracevv(x) do { if (verbose > 1) fprintf x ; } while (0) +# define Tracec(c, x) do { if (verbose && (c)) fprintf x ; } while (0) +# define Tracecv(c, x) do { if (verbose > 1 && (c)) fprintf x ; } while (0) +#else +# define Assert(cond, msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c, x) +# define Tracecv(c, x) +#endif + +static long __initdata bytes_out; +static void flush_window(void); + +static __init void error(char *x) +{ + panic("%s", x); +} + +static __init int fill_inbuf(void) +{ + error("ran out of input data"); + return 0; +} + #ifdef RCSID static char rcsid[] = "#Id: inflate.c,v 0.14 1993/06/10 13:27:04 jloup Exp #"; #endif @@ -1302,3 +1364,54 @@ static int INIT gunzip(void) error("out of input data"); return -1; } + +static __init void flush_window(void) +{ + /* + * The window is equal to the output buffer therefore only need to + * compute the crc. + */ + unsigned long c = crc; + unsigned n; + unsigned char *in, ch; + + in = window; + for ( n = 0; n < outcnt; n++ ) + { + ch = *in++; + c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + + bytes_out += (unsigned long)outcnt; + outcnt = 0; +} + +static __init int perform_gunzip(char *output, char *image, unsigned long image_len) +{ + int rc; + + window = (unsigned char *)output; + + free_mem_ptr = (unsigned long)alloc_xenheap_pages(HEAPORDER, 0); + free_mem_end_ptr = free_mem_ptr + (PAGE_SIZE << HEAPORDER); + + inbuf = (unsigned char *)image; + insize = image_len; + inptr = 0; + + makecrc(); + + if ( gunzip() < 0 ) + { + rc = -EINVAL; + } + else + { + rc = 0; + } + + free_xenheap_pages((void *)free_mem_ptr, HEAPORDER); + + return rc; +} ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] xen: move perform_gunzip to common 2015-08-13 9:28 ` Stefano Stabellini @ 2015-08-13 9:57 ` Jan Beulich 2015-08-13 10:17 ` Ian Campbell 0 siblings, 1 reply; 20+ messages in thread From: Jan Beulich @ 2015-08-13 9:57 UTC (permalink / raw) To: StefanoStabellini; +Cc: andrew.cooper3, Ian.Campbell, xen-devel >>> On 13.08.15 at 11:28, <stefano.stabellini@eu.citrix.com> wrote: > On Thu, 13 Aug 2015, Jan Beulich wrote: >> >>> On 12.08.15 at 18:15, <stefano.stabellini@eu.citrix.com> wrote: >> > On Wed, 12 Aug 2015, Jan Beulich wrote: >> >> >>> On 12.08.15 at 16:47, <stefano.stabellini@eu.citrix.com> wrote: >> >> > @@ -31,8 +33,15 @@ typedef int decompress_fn(unsigned char *inbuf, unsigned int len, >> >> > * dependent). >> >> > */ >> >> > >> >> > -decompress_fn bunzip2, unxz, unlzma, unlzo, unlz4; >> >> > +decompress_fn perform_gunzip, bunzip2, unxz, unlzma, unlzo, unlz4; >> >> > >> >> > int decompress(void *inbuf, unsigned int len, void *outbuf); >> >> > >> >> > +static inline unsigned long output_length(char *image, unsigned long image_len) >> >> >> >> Neither of the callers gets moved out of bzimage.c - why does this >> >> function need to move? >> > >> > We'll use it on arm. >> >> Hmm, the way it is used on x86 makes it quite architecture specific >> (namely because of the assumption that the size is also in said >> place for non-gz compression methods). I'd therefore prefer code >> duplication over code sharing here. > > Actually after seeing the size and quality of the resulting patches, I > am starting to feel the same way. > > In terms of code changes, I was thinking that the best result would be > moving the "boilerplate" code from xen/arch/x86/bzimage.c to > xen/common/inflate.c, see below, then the interface would become just > perform_gunzip and gzip_check. But I guess you wouldn't want inflate.c > to be modified, right? Yes, unless really unavoidable. > Alternatively we could move it to a new file, let's call it gunzip.h, > that would #include "inflate.c", so: > > bzimage.c -- #include --> gunzip.h -- #include --> inflate.c > > And again we just leave the perform_gunzip and gzip_check calls in > bzimage.c. What do you think? That's an option. Jan ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] xen: move perform_gunzip to common 2015-08-13 9:57 ` Jan Beulich @ 2015-08-13 10:17 ` Ian Campbell 2015-08-13 10:27 ` Jan Beulich 0 siblings, 1 reply; 20+ messages in thread From: Ian Campbell @ 2015-08-13 10:17 UTC (permalink / raw) To: Jan Beulich, StefanoStabellini; +Cc: andrew.cooper3, xen-devel On Thu, 2015-08-13 at 03:57 -0600, Jan Beulich wrote: > > > > > > On 13.08.15 at 11:28, <stefano.stabellini@eu.citrix.com> wrote: > > On Thu, 13 Aug 2015, Jan Beulich wrote: > > > > > > On 12.08.15 at 18:15, <stefano.stabellini@eu.citrix.com> wrote: > > > > On Wed, 12 Aug 2015, Jan Beulich wrote: > > > > > > > > On 12.08.15 at 16:47, <stefano.stabellini@eu.citrix.com> > > > > > > > > wrote: > > > > > > @@ -31,8 +33,15 @@ typedef int decompress_fn(unsigned char > > > > > > *inbuf, unsigned int len, > > > > > > * dependent). > > > > > > */ > > > > > > > > > > > > -decompress_fn bunzip2, unxz, unlzma, unlzo, unlz4; > > > > > > +decompress_fn perform_gunzip, bunzip2, unxz, unlzma, unlzo, > > > > > > unlz4; > > > > > > > > > > > > int decompress(void *inbuf, unsigned int len, void *outbuf); > > > > > > > > > > > > +static inline unsigned long output_length(char *image, > > > > > > unsigned long image_len) > > > > > > > > > > Neither of the callers gets moved out of bzimage.c - why does > > > > > this > > > > > function need to move? > > > > > > > > We'll use it on arm. > > > > > > Hmm, the way it is used on x86 makes it quite architecture specific > > > (namely because of the assumption that the size is also in said > > > place for non-gz compression methods). I'd therefore prefer code > > > duplication over code sharing here. > > > > Actually after seeing the size and quality of the resulting patches, I > > am starting to feel the same way. > > > > In terms of code changes, I was thinking that the best result would be > > moving the "boilerplate" code from xen/arch/x86/bzimage.c to > > xen/common/inflate.c, see below, then the interface would become just > > perform_gunzip and gzip_check. But I guess you wouldn't want inflate.c > > to be modified, right? > > Yes, unless really unavoidable. > > > Alternatively we could move it to a new file, let's call it gunzip.h, > > that would #include "inflate.c", so: > > > > bzimage.c -- #include --> gunzip.h -- #include --> inflate.c > > > > And again we just leave the perform_gunzip and gzip_check calls in > > bzimage.c. What do you think? How about putting perform_gunzip and gzip_check into a new gunzip.c which includes inflate.c? ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 1/2] xen: move perform_gunzip to common 2015-08-13 10:17 ` Ian Campbell @ 2015-08-13 10:27 ` Jan Beulich 0 siblings, 0 replies; 20+ messages in thread From: Jan Beulich @ 2015-08-13 10:27 UTC (permalink / raw) To: Ian Campbell, StefanoStabellini; +Cc: andrew.cooper3, xen-devel >>> On 13.08.15 at 12:17, <ian.campbell@citrix.com> wrote: > On Thu, 2015-08-13 at 03:57 -0600, Jan Beulich wrote: >> > >> > > > On 13.08.15 at 11:28, <stefano.stabellini@eu.citrix.com> wrote: >> > On Thu, 13 Aug 2015, Jan Beulich wrote: >> > > > > > On 12.08.15 at 18:15, <stefano.stabellini@eu.citrix.com> wrote: >> > > > On Wed, 12 Aug 2015, Jan Beulich wrote: >> > > > > > > > On 12.08.15 at 16:47, <stefano.stabellini@eu.citrix.com> >> > > > > > > > wrote: >> > > > > > @@ -31,8 +33,15 @@ typedef int decompress_fn(unsigned char >> > > > > > *inbuf, unsigned int len, >> > > > > > * dependent). >> > > > > > */ >> > > > > > >> > > > > > -decompress_fn bunzip2, unxz, unlzma, unlzo, unlz4; >> > > > > > +decompress_fn perform_gunzip, bunzip2, unxz, unlzma, unlzo, >> > > > > > unlz4; >> > > > > > >> > > > > > int decompress(void *inbuf, unsigned int len, void *outbuf); >> > > > > > >> > > > > > +static inline unsigned long output_length(char *image, >> > > > > > unsigned long image_len) >> > > > > >> > > > > Neither of the callers gets moved out of bzimage.c - why does >> > > > > this >> > > > > function need to move? >> > > > >> > > > We'll use it on arm. >> > > >> > > Hmm, the way it is used on x86 makes it quite architecture specific >> > > (namely because of the assumption that the size is also in said >> > > place for non-gz compression methods). I'd therefore prefer code >> > > duplication over code sharing here. >> > >> > Actually after seeing the size and quality of the resulting patches, I >> > am starting to feel the same way. >> > >> > In terms of code changes, I was thinking that the best result would be >> > moving the "boilerplate" code from xen/arch/x86/bzimage.c to >> > xen/common/inflate.c, see below, then the interface would become just >> > perform_gunzip and gzip_check. But I guess you wouldn't want inflate.c >> > to be modified, right? >> >> Yes, unless really unavoidable. >> >> > Alternatively we could move it to a new file, let's call it gunzip.h, >> > that would #include "inflate.c", so: >> > >> > bzimage.c -- #include --> gunzip.h -- #include --> inflate.c >> > >> > And again we just leave the perform_gunzip and gzip_check calls in >> > bzimage.c. What do you think? > > How about putting perform_gunzip and gzip_check into a new gunzip.c which > includes inflate.c? Would seem as good to me, provided specifically the output_length() helper then can stay where it is. Jan ^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 14:47 [PATCH 0/2] support compressed kernels on ARM64 Stefano Stabellini 2015-08-12 14:47 ` [PATCH 1/2] xen: move perform_gunzip to common Stefano Stabellini @ 2015-08-12 14:47 ` Stefano Stabellini 2015-08-12 15:03 ` Ian Campbell ` (2 more replies) 1 sibling, 3 replies; 20+ messages in thread From: Stefano Stabellini @ 2015-08-12 14:47 UTC (permalink / raw) To: xen-devel; +Cc: julien.grall, ian.campbell, Stefano Stabellini Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> CC: julien.grall@citrix.com CC: ian.campbell@citrix.com --- xen/arch/arm/kernel.c | 36 ++++++++++++++++++++++++++++++++++++ xen/common/Makefile | 2 +- xen/include/asm-arm/byteorder.h | 2 ++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c index f641b12..ca50cdd 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/decompress.h> +#include <xen/vmap.h> #include "kernel.h" @@ -310,6 +312,38 @@ static int kernel_zimage64_probe(struct kernel_info *info, return 0; } + +static int kernel_zimage64_compressed_probe(struct kernel_info *info, + paddr_t addr, paddr_t size) +{ + char *output, *input; + unsigned char magic[2]; + int rc; + unsigned kernel_order_in; + unsigned kernel_order_out; + paddr_t output_size; + + copy_from_paddr(magic, addr, sizeof(magic)); + + if (!((magic[0] == 0x1f) && ((magic[1] == 0x8b) || (magic[1] == 0x9e)))) + return -EINVAL; + + kernel_order_in = get_order_from_bytes(size); + input = (char *)ioremap_cache(addr, size); + + output_size = output_length(input, size); + kernel_order_out = get_order_from_bytes(output_size); + output = (char *)alloc_xenheap_pages(kernel_order_out, 0); + + rc = decompress(input, size, output); + clean_dcache_va_range(output, output_size); + iounmap(input); + + if (rc != 0) + return rc; + + return kernel_zimage64_probe(info, virt_to_maddr(output), output_size); +} #endif /* @@ -466,6 +500,8 @@ int kernel_probe(struct kernel_info *info) #ifdef CONFIG_ARM_64 rc = kernel_zimage64_probe(info, start, size); if (rc < 0) + rc = kernel_zimage64_compressed_probe(info, start, size); + if (rc < 0) #endif rc = kernel_uimage_probe(info, start, size); if (rc < 0) diff --git a/xen/common/Makefile b/xen/common/Makefile index 0a4d4fa..a8aefc6 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -56,7 +56,7 @@ obj-y += vsprintf.o obj-y += wait.o obj-y += xmalloc_tlsf.o -obj-bin-$(CONFIG_X86) += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) +obj-bin-y += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) obj-$(perfc) += perfc.o obj-$(crash_debug) += gdbstub.o diff --git a/xen/include/asm-arm/byteorder.h b/xen/include/asm-arm/byteorder.h index 9c712c4..3b7feda 100644 --- a/xen/include/asm-arm/byteorder.h +++ b/xen/include/asm-arm/byteorder.h @@ -5,6 +5,8 @@ #include <xen/byteorder/little_endian.h> +#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + #endif /* __ASM_ARM_BYTEORDER_H__ */ /* * Local variables: -- 1.7.10.4 ^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 14:47 ` [PATCH 2/2] xen/arm: support compressed kernels Stefano Stabellini @ 2015-08-12 15:03 ` Ian Campbell 2015-08-12 15:20 ` Julien Grall 2015-08-12 15:22 ` Stefano Stabellini 2015-08-12 15:09 ` Julien Grall 2015-08-12 16:35 ` Andrew Cooper 2 siblings, 2 replies; 20+ messages in thread From: Ian Campbell @ 2015-08-12 15:03 UTC (permalink / raw) To: Stefano Stabellini, xen-devel; +Cc: julien.grall On Wed, 2015-08-12 at 15:47 +0100, Stefano Stabellini wrote: > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > CC: julien.grall@citrix.com > CC: ian.campbell@citrix.com > --- > xen/arch/arm/kernel.c | 36 > ++++++++++++++++++++++++++++++++++++ > xen/common/Makefile | 2 +- > xen/include/asm-arm/byteorder.h | 2 ++ > 3 files changed, 39 insertions(+), 1 deletion(-) > > diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c > index f641b12..ca50cdd 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/decompress.h> > +#include <xen/vmap.h> > > #include "kernel.h" > > @@ -310,6 +312,38 @@ static int kernel_zimage64_probe(struct kernel_info > *info, > > return 0; > } > + > +static int kernel_zimage64_compressed_probe(struct kernel_info *info, > + paddr_t addr, paddr_t size) > +{ > + char *output, *input; > + unsigned char magic[2]; > + int rc; > + unsigned kernel_order_in; > + unsigned kernel_order_out; > + paddr_t output_size; > + > + copy_from_paddr(magic, addr, sizeof(magic)); > + > + if (!((magic[0] == 0x1f) && ((magic[1] == 0x8b) || (magic[1] == 0x9e)))) > + return -EINVAL; This is an open coded check_gzip. I think you could call that function on magic? > + > + kernel_order_in = get_order_from_bytes(size); > + input = (char *)ioremap_cache(addr, size); I don't think you need to cast this, do you? It's a void * already. > + > + output_size = output_length(input, size); > + kernel_order_out = get_order_from_bytes(output_size); > + output = (char *)alloc_xenheap_pages(kernel_order_out, 0); Likewise. Where is this buffer freed? When I said IRL we recover the kernel memory I meant the thing in the boot modules list. You might be able to get away with flipping the boot module over to this, but that would have ordering constraints which I didn't check, it'll probably get subtle fast. > + > + rc = decompress(input, size, output); > + clean_dcache_va_range(output, output_size); > + iounmap(input); > + > + if (rc != 0) > + return rc; > + > + return kernel_zimage64_probe(info, virt_to_maddr(output), output_size); > +} > #endif > > /* > @@ -466,6 +500,8 @@ int kernel_probe(struct kernel_info *info) > #ifdef CONFIG_ARM_64 > rc = kernel_zimage64_probe(info, start, size); > if (rc < 0) > + rc = kernel_zimage64_compressed_probe(info, start, size); I don't see a reason not to support compressed 32 bit kernels too. All it would take would be to try and uncompress the buffer first before falling through to the various probe routines, instead of chaining a probe into the decompressor. Probably the easiest way to solve this and the buffer allocation issue above would be to always either copy or decompress the original kernel into a buffer and then change all the probe function to use a virtual address instead of an maddr (which might have tricky cache interactions since the mapping still exists). > + if (rc < 0) > #endif > rc = kernel_uimage_probe(info, start, size); > if (rc < 0) > diff --git a/xen/common/Makefile b/xen/common/Makefile > index 0a4d4fa..a8aefc6 100644 > --- a/xen/common/Makefile > +++ b/xen/common/Makefile > @@ -56,7 +56,7 @@ obj-y += vsprintf.o > obj-y += wait.o > obj-y += xmalloc_tlsf.o > > -obj-bin-$(CONFIG_X86) += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) > +obj-bin-y += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) I don't think we need/want earlycpio support on ARM (not yet anyway). > > obj-$(perfc) += perfc.o > obj-$(crash_debug) += gdbstub.o > diff --git a/xen/include/asm-arm/byteorder.h b/xen/include/asm > -arm/byteorder.h > index 9c712c4..3b7feda 100644 > --- a/xen/include/asm-arm/byteorder.h > +++ b/xen/include/asm-arm/byteorder.h > @@ -5,6 +5,8 @@ > > #include <xen/byteorder/little_endian.h> > > +#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS While CONFIG_HAVE_UNALIGNED_ACCESS might be true on arm64 it may not be the case that it is efficient. Also I'm not sure about arm32 at all. > + > #endif /* __ASM_ARM_BYTEORDER_H__ */ > /* > * Local variables: ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 15:03 ` Ian Campbell @ 2015-08-12 15:20 ` Julien Grall 2015-08-12 15:22 ` Stefano Stabellini 1 sibling, 0 replies; 20+ messages in thread From: Julien Grall @ 2015-08-12 15:20 UTC (permalink / raw) To: Ian Campbell, Stefano Stabellini, xen-devel On 12/08/15 16:03, Ian Campbell wrote: > On Wed, 2015-08-12 at 15:47 +0100, Stefano Stabellini wrote: >> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> >> CC: julien.grall@citrix.com >> CC: ian.campbell@citrix.com >> --- >> xen/arch/arm/kernel.c | 36 >> ++++++++++++++++++++++++++++++++++++ >> xen/common/Makefile | 2 +- >> xen/include/asm-arm/byteorder.h | 2 ++ >> 3 files changed, 39 insertions(+), 1 deletion(-) >> >> diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c >> index f641b12..ca50cdd 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/decompress.h> >> +#include <xen/vmap.h> >> >> #include "kernel.h" >> >> @@ -310,6 +312,38 @@ static int kernel_zimage64_probe(struct kernel_info >> *info, >> >> return 0; >> } >> + >> +static int kernel_zimage64_compressed_probe(struct kernel_info *info, >> + paddr_t addr, paddr_t size) >> +{ >> + char *output, *input; >> + unsigned char magic[2]; >> + int rc; >> + unsigned kernel_order_in; >> + unsigned kernel_order_out; >> + paddr_t output_size; >> + >> + copy_from_paddr(magic, addr, sizeof(magic)); >> + >> + if (!((magic[0] == 0x1f) && ((magic[1] == 0x8b) || (magic[1] == 0x9e)))) >> + return -EINVAL; > > This is an open coded check_gzip. I think you could call that function on > magic? > >> + >> + kernel_order_in = get_order_from_bytes(size); >> + input = (char *)ioremap_cache(addr, size); > > I don't think you need to cast this, do you? It's a void * already. > >> + >> + output_size = output_length(input, size); >> + kernel_order_out = get_order_from_bytes(output_size); >> + output = (char *)alloc_xenheap_pages(kernel_order_out, 0); > > Likewise. > > Where is this buffer freed? > > When I said IRL we recover the kernel memory I meant the thing in the boot > modules list. You might be able to get away with flipping the boot module > over to this, but that would have ordering constraints which I didn't > check, it'll probably get subtle fast. > >> + >> + rc = decompress(input, size, output); >> + clean_dcache_va_range(output, output_size); >> + iounmap(input); >> + >> + if (rc != 0) >> + return rc; >> + >> + return kernel_zimage64_probe(info, virt_to_maddr(output), output_size); > > > >> +} >> #endif >> >> /* >> @@ -466,6 +500,8 @@ int kernel_probe(struct kernel_info *info) >> #ifdef CONFIG_ARM_64 >> rc = kernel_zimage64_probe(info, start, size); >> if (rc < 0) >> + rc = kernel_zimage64_compressed_probe(info, start, size); > > I don't see a reason not to support compressed 32 bit kernels too. All it > would take would be to try and uncompress the buffer first before falling > through to the various probe routines, instead of chaining a probe into the > decompressor. > > Probably the easiest way to solve this and the buffer allocation issue > above would be to always either copy or decompress the original kernel into > a buffer and then change all the probe function to use a virtual address > instead of an maddr (which might have tricky cache interactions since the > mapping still exists). > >> + if (rc < 0) >> #endif >> rc = kernel_uimage_probe(info, start, size); >> if (rc < 0) >> diff --git a/xen/common/Makefile b/xen/common/Makefile >> index 0a4d4fa..a8aefc6 100644 >> --- a/xen/common/Makefile >> +++ b/xen/common/Makefile >> @@ -56,7 +56,7 @@ obj-y += vsprintf.o >> obj-y += wait.o >> obj-y += xmalloc_tlsf.o >> >> -obj-bin-$(CONFIG_X86) += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) >> +obj-bin-y += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) > > I don't think we need/want earlycpio support on ARM (not yet anyway). > >> >> obj-$(perfc) += perfc.o >> obj-$(crash_debug) += gdbstub.o >> diff --git a/xen/include/asm-arm/byteorder.h b/xen/include/asm >> -arm/byteorder.h >> index 9c712c4..3b7feda 100644 >> --- a/xen/include/asm-arm/byteorder.h >> +++ b/xen/include/asm-arm/byteorder.h >> @@ -5,6 +5,8 @@ >> >> #include <xen/byteorder/little_endian.h> >> >> +#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS > > While CONFIG_HAVE_UNALIGNED_ACCESS might be true on arm64 it may not be the > case that it is efficient. Also I'm not sure about arm32 at all. ARM32 has alignment checking enabled. So any unaligned access would result to a data abort. FWIW, on ARM64 the alignment trap has been disabled because mem* primitives are relying on the hardware handling misalignment: 58bbe7d71239db508c30099bf7b6db7c458f3336 " xen: arm64: disable alignment traps " IIRC, the unaligned access on ARM processor tend to be slow. I remembered to read an article about it a couple of years ago. Regards, -- Julien Grall ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 15:03 ` Ian Campbell 2015-08-12 15:20 ` Julien Grall @ 2015-08-12 15:22 ` Stefano Stabellini 2015-08-12 15:27 ` Julien Grall ` (2 more replies) 1 sibling, 3 replies; 20+ messages in thread From: Stefano Stabellini @ 2015-08-12 15:22 UTC (permalink / raw) To: Ian Campbell; +Cc: julien.grall, xen-devel, Stefano Stabellini On Wed, 12 Aug 2015, Ian Campbell wrote: > On Wed, 2015-08-12 at 15:47 +0100, Stefano Stabellini wrote: > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > CC: julien.grall@citrix.com > > CC: ian.campbell@citrix.com > > --- > > xen/arch/arm/kernel.c | 36 > > ++++++++++++++++++++++++++++++++++++ > > xen/common/Makefile | 2 +- > > xen/include/asm-arm/byteorder.h | 2 ++ > > 3 files changed, 39 insertions(+), 1 deletion(-) > > > > diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c > > index f641b12..ca50cdd 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/decompress.h> > > +#include <xen/vmap.h> > > > > #include "kernel.h" > > > > @@ -310,6 +312,38 @@ static int kernel_zimage64_probe(struct kernel_info > > *info, > > > > return 0; > > } > > + > > +static int kernel_zimage64_compressed_probe(struct kernel_info *info, > > + paddr_t addr, paddr_t size) > > +{ > > + char *output, *input; > > + unsigned char magic[2]; > > + int rc; > > + unsigned kernel_order_in; > > + unsigned kernel_order_out; > > + paddr_t output_size; > > + > > + copy_from_paddr(magic, addr, sizeof(magic)); > > + > > + if (!((magic[0] == 0x1f) && ((magic[1] == 0x8b) || (magic[1] == 0x9e)))) > > + return -EINVAL; > > This is an open coded check_gzip. I think you could call that function on > magic? > > > + > > + kernel_order_in = get_order_from_bytes(size); > > + input = (char *)ioremap_cache(addr, size); > > I don't think you need to cast this, do you? It's a void * already. > > > + > > + output_size = output_length(input, size); > > + kernel_order_out = get_order_from_bytes(output_size); > > + output = (char *)alloc_xenheap_pages(kernel_order_out, 0); > > Likewise. > > Where is this buffer freed? > > When I said IRL we recover the kernel memory I meant the thing in the boot > modules list. You might be able to get away with flipping the boot module > over to this, but that would have ordering constraints which I didn't > check, it'll probably get subtle fast. > > > + > > + rc = decompress(input, size, output); > > + clean_dcache_va_range(output, output_size); > > + iounmap(input); > > + > > + if (rc != 0) > > + return rc; > > + > > + return kernel_zimage64_probe(info, virt_to_maddr(output), output_size); > > > > > +} > > #endif > > > > /* > > @@ -466,6 +500,8 @@ int kernel_probe(struct kernel_info *info) > > #ifdef CONFIG_ARM_64 > > rc = kernel_zimage64_probe(info, start, size); > > if (rc < 0) > > + rc = kernel_zimage64_compressed_probe(info, start, size); > > I don't see a reason not to support compressed 32 bit kernels too. All it > would take would be to try and uncompress the buffer first before falling > through to the various probe routines, instead of chaining a probe into the > decompressor. > > Probably the easiest way to solve this and the buffer allocation issue > above would be to always either copy or decompress the original kernel into > a buffer and then change all the probe function to use a virtual address > instead of an maddr (which might have tricky cache interactions since the > mapping still exists). I'll give it a look > > + if (rc < 0) > > #endif > > rc = kernel_uimage_probe(info, start, size); > > if (rc < 0) > > diff --git a/xen/common/Makefile b/xen/common/Makefile > > index 0a4d4fa..a8aefc6 100644 > > --- a/xen/common/Makefile > > +++ b/xen/common/Makefile > > @@ -56,7 +56,7 @@ obj-y += vsprintf.o > > obj-y += wait.o > > obj-y += xmalloc_tlsf.o > > > > -obj-bin-$(CONFIG_X86) += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) > > +obj-bin-y += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) > > I don't think we need/want earlycpio support on ARM (not yet anyway). Unfortunately it is not possible to only compile some and not all because decompress.c makes use of them all. > > obj-$(perfc) += perfc.o > > obj-$(crash_debug) += gdbstub.o > > diff --git a/xen/include/asm-arm/byteorder.h b/xen/include/asm > > -arm/byteorder.h > > index 9c712c4..3b7feda 100644 > > --- a/xen/include/asm-arm/byteorder.h > > +++ b/xen/include/asm-arm/byteorder.h > > @@ -5,6 +5,8 @@ > > > > #include <xen/byteorder/little_endian.h> > > > > +#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS > > While CONFIG_HAVE_UNALIGNED_ACCESS might be true on arm64 it may not be the > case that it is efficient. Also I'm not sure about arm32 at all. It is true on arm archs >= v8, so we should be fine. See: http://lwn.net/Articles/540022/ ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 15:22 ` Stefano Stabellini @ 2015-08-12 15:27 ` Julien Grall 2015-08-12 15:35 ` Jan Beulich 2015-08-12 15:43 ` Ian Campbell 2 siblings, 0 replies; 20+ messages in thread From: Julien Grall @ 2015-08-12 15:27 UTC (permalink / raw) To: Stefano Stabellini, Ian Campbell; +Cc: xen-devel On 12/08/15 16:22, Stefano Stabellini wrote: >>> obj-$(perfc) += perfc.o >>> obj-$(crash_debug) += gdbstub.o >>> diff --git a/xen/include/asm-arm/byteorder.h b/xen/include/asm >>> -arm/byteorder.h >>> index 9c712c4..3b7feda 100644 >>> --- a/xen/include/asm-arm/byteorder.h >>> +++ b/xen/include/asm-arm/byteorder.h >>> @@ -5,6 +5,8 @@ >>> >>> #include <xen/byteorder/little_endian.h> >>> >>> +#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS >> >> While CONFIG_HAVE_UNALIGNED_ACCESS might be true on arm64 it may not be the >> case that it is efficient. Also I'm not sure about arm32 at all. > > It is true on arm archs >= v8, so we should be fine. See: I guess you meant v6? Although, unaligned access are not allowed in Xen on ARM32. See arm32/head.S:353 Given that the uncompress code is only used for decompressing DOM0 kernel, I don't think it's worth to enable unaligned access. Regards, -- Julien Grall ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 15:22 ` Stefano Stabellini 2015-08-12 15:27 ` Julien Grall @ 2015-08-12 15:35 ` Jan Beulich 2015-08-12 15:40 ` Stefano Stabellini 2015-08-12 15:43 ` Ian Campbell 2 siblings, 1 reply; 20+ messages in thread From: Jan Beulich @ 2015-08-12 15:35 UTC (permalink / raw) To: Stefano Stabellini; +Cc: julien.grall, xen-devel, Ian Campbell >>> On 12.08.15 at 17:22, <stefano.stabellini@eu.citrix.com> wrote: > On Wed, 12 Aug 2015, Ian Campbell wrote: >> On Wed, 2015-08-12 at 15:47 +0100, Stefano Stabellini wrote: >> > --- a/xen/common/Makefile >> > +++ b/xen/common/Makefile >> > @@ -56,7 +56,7 @@ obj-y += vsprintf.o >> > obj-y += wait.o >> > obj-y += xmalloc_tlsf.o >> > >> > -obj-bin-$(CONFIG_X86) += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) >> > +obj-bin-y += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) >> >> I don't think we need/want earlycpio support on ARM (not yet anyway). > > Unfortunately it is not possible to only compile some and not all > because decompress.c makes use of them all. Mind pointing out the reference into earlycpio.c? Jan ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 15:35 ` Jan Beulich @ 2015-08-12 15:40 ` Stefano Stabellini 0 siblings, 0 replies; 20+ messages in thread From: Stefano Stabellini @ 2015-08-12 15:40 UTC (permalink / raw) To: Jan Beulich; +Cc: julien.grall, xen-devel, Ian Campbell, Stefano Stabellini On Wed, 12 Aug 2015, Jan Beulich wrote: > >>> On 12.08.15 at 17:22, <stefano.stabellini@eu.citrix.com> wrote: > > On Wed, 12 Aug 2015, Ian Campbell wrote: > >> On Wed, 2015-08-12 at 15:47 +0100, Stefano Stabellini wrote: > >> > --- a/xen/common/Makefile > >> > +++ b/xen/common/Makefile > >> > @@ -56,7 +56,7 @@ obj-y += vsprintf.o > >> > obj-y += wait.o > >> > obj-y += xmalloc_tlsf.o > >> > > >> > -obj-bin-$(CONFIG_X86) += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) > >> > +obj-bin-y += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo unlz4 earlycpio,$(n).init.o) > >> > >> I don't think we need/want earlycpio support on ARM (not yet anyway). > > > > Unfortunately it is not possible to only compile some and not all > > because decompress.c makes use of them all. > > Mind pointing out the reference into earlycpio.c? Sorry, all but earlycpio.c :-/ I'll make the change ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 15:22 ` Stefano Stabellini 2015-08-12 15:27 ` Julien Grall 2015-08-12 15:35 ` Jan Beulich @ 2015-08-12 15:43 ` Ian Campbell 2 siblings, 0 replies; 20+ messages in thread From: Ian Campbell @ 2015-08-12 15:43 UTC (permalink / raw) To: Stefano Stabellini; +Cc: julien.grall, xen-devel On Wed, 2015-08-12 at 16:22 +0100, Stefano Stabellini wrote: > -obj-bin-$(CONFIG_X86) += $(foreach n,decompress gunzip bunzip2 unxz > > > unlzma unlzo unlz4 earlycpio,$(n).init.o) > > > +obj-bin-y += $(foreach n,decompress gunzip bunzip2 unxz unlzma unlzo > > > unlz4 earlycpio,$(n).init.o) > > > > I don't think we need/want earlycpio support on ARM (not yet anyway). > > Unfortunately it is not possible to only compile some and not all > because decompress.c makes use of them all. earlycpio isn't a decompression algorithm though, it just happens to be bundled into the same obj-bin. I don't see any sign of cpio support in decompress.c (since that wouldn't make sense). > > > > obj-$(perfc) += perfc.o > > > obj-$(crash_debug) += gdbstub.o > > > diff --git a/xen/include/asm-arm/byteorder.h b/xen/include/asm > > > -arm/byteorder.h > > > index 9c712c4..3b7feda 100644 > > > --- a/xen/include/asm-arm/byteorder.h > > > +++ b/xen/include/asm-arm/byteorder.h > > > @@ -5,6 +5,8 @@ > > > > > > #include <xen/byteorder/little_endian.h> > > > > > > +#define CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS > > > > While CONFIG_HAVE_UNALIGNED_ACCESS might be true on arm64 it may not be > > the > > case that it is efficient. Also I'm not sure about arm32 at all. > > It is true on arm archs >= v8, I'm not sure about that. > so we should be fine. See: > > http://lwn.net/Articles/540022/ Even this says it is not always the best option, but this is not fast path code so never mind. Also if it isn't true for armv7 you shouldn't set it unconditionally, it needs either an ifdef or for arm{32,64}/byteorder.h to have it. On x86 this #define is in config.h, please lets be consistent. Also that makes more sense anyway since alignment != byteorder. Ian. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 14:47 ` [PATCH 2/2] xen/arm: support compressed kernels Stefano Stabellini 2015-08-12 15:03 ` Ian Campbell @ 2015-08-12 15:09 ` Julien Grall 2015-08-12 16:35 ` Andrew Cooper 2 siblings, 0 replies; 20+ messages in thread From: Julien Grall @ 2015-08-12 15:09 UTC (permalink / raw) To: Stefano Stabellini, xen-devel; +Cc: ian.campbell Hi Stefano, I'm sure you don't support all kind of compressed kernels. Can you example in the commit message which one you are supporting? On 12/08/15 15:47, Stefano Stabellini wrote: > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > CC: julien.grall@citrix.com > CC: ian.campbell@citrix.com > --- > xen/arch/arm/kernel.c | 36 ++++++++++++++++++++++++++++++++++++ > xen/common/Makefile | 2 +- > xen/include/asm-arm/byteorder.h | 2 ++ > 3 files changed, 39 insertions(+), 1 deletion(-) > > diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c > index f641b12..ca50cdd 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/decompress.h> > +#include <xen/vmap.h> > > #include "kernel.h" > > @@ -310,6 +312,38 @@ static int kernel_zimage64_probe(struct kernel_info *info, > > return 0; > } > + > +static int kernel_zimage64_compressed_probe(struct kernel_info *info, > + paddr_t addr, paddr_t size) > +{ > + char *output, *input; > + unsigned char magic[2]; > + int rc; > + unsigned kernel_order_in; > + unsigned kernel_order_out; > + paddr_t output_size; > + > + copy_from_paddr(magic, addr, sizeof(magic)); > + > + if (!((magic[0] == 0x1f) && ((magic[1] == 0x8b) || (magic[1] == 0x9e)))) Please add a comment to explain what this magic means. Maybe you want to use gzip_check? > + return -EINVAL; > + > + kernel_order_in = get_order_from_bytes(size); > + input = (char *)ioremap_cache(addr, size); Cast not necessary. And please check that we effectively were able to map the kernel. > + > + output_size = output_length(input, size); > + kernel_order_out = get_order_from_bytes(output_size); > + output = (char *)alloc_xenheap_pages(kernel_order_out, 0); Ditto. > + > + rc = decompress(input, size, output); > + clean_dcache_va_range(output, output_size); > + iounmap(input); > + > + if (rc != 0) > + return rc; > + > + return kernel_zimage64_probe(info, virt_to_maddr(output), output_size); > +} > #endif > > /* > @@ -466,6 +500,8 @@ int kernel_probe(struct kernel_info *info) > #ifdef CONFIG_ARM_64 > rc = kernel_zimage64_probe(info, start, size); > if (rc < 0) > + rc = kernel_zimage64_compressed_probe(info, start, size); > + if (rc < 0) > #endif > rc = kernel_uimage_probe(info, start, size); > if (rc < 0) Regards, -- Julien Grall ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 14:47 ` [PATCH 2/2] xen/arm: support compressed kernels Stefano Stabellini 2015-08-12 15:03 ` Ian Campbell 2015-08-12 15:09 ` Julien Grall @ 2015-08-12 16:35 ` Andrew Cooper 2015-08-12 17:00 ` Julien Grall 2 siblings, 1 reply; 20+ messages in thread From: Andrew Cooper @ 2015-08-12 16:35 UTC (permalink / raw) To: Stefano Stabellini, xen-devel; +Cc: julien.grall, ian.campbell On 12/08/15 15:47, Stefano Stabellini wrote: > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > CC: julien.grall@citrix.com > CC: ian.campbell@citrix.com > --- > xen/arch/arm/kernel.c | 36 ++++++++++++++++++++++++++++++++++++ > xen/common/Makefile | 2 +- > xen/include/asm-arm/byteorder.h | 2 ++ > 3 files changed, 39 insertions(+), 1 deletion(-) > > diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c > index f641b12..ca50cdd 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/decompress.h> > +#include <xen/vmap.h> > > #include "kernel.h" > > @@ -310,6 +312,38 @@ static int kernel_zimage64_probe(struct kernel_info *info, > > return 0; > } > + > +static int kernel_zimage64_compressed_probe(struct kernel_info *info, > + paddr_t addr, paddr_t size) > +{ > + char *output, *input; > + unsigned char magic[2]; > + int rc; > + unsigned kernel_order_in; > + unsigned kernel_order_out; > + paddr_t output_size; > + > + copy_from_paddr(magic, addr, sizeof(magic)); Need a size check before assuming sufficient length. (All of the arm probe functions suffer in a similar way.) > + > + if (!((magic[0] == 0x1f) && ((magic[1] == 0x8b) || (magic[1] == 0x9e)))) > + return -EINVAL; > + > + kernel_order_in = get_order_from_bytes(size); > + input = (char *)ioremap_cache(addr, size); > + > + output_size = output_length(input, size); > + kernel_order_out = get_order_from_bytes(output_size); > + output = (char *)alloc_xenheap_pages(kernel_order_out, 0); > + > + rc = decompress(input, size, output); > + clean_dcache_va_range(output, output_size); > + iounmap(input); > + > + if (rc != 0) Xen style. ~Andrew ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH 2/2] xen/arm: support compressed kernels 2015-08-12 16:35 ` Andrew Cooper @ 2015-08-12 17:00 ` Julien Grall 0 siblings, 0 replies; 20+ messages in thread From: Julien Grall @ 2015-08-12 17:00 UTC (permalink / raw) To: Andrew Cooper, Stefano Stabellini, xen-devel; +Cc: ian.campbell On 12/08/15 17:35, Andrew Cooper wrote: >> + >> +static int kernel_zimage64_compressed_probe(struct kernel_info *info, >> + paddr_t addr, paddr_t size) >> +{ >> + char *output, *input; >> + unsigned char magic[2]; >> + int rc; >> + unsigned kernel_order_in; >> + unsigned kernel_order_out; >> + paddr_t output_size; >> + >> + copy_from_paddr(magic, addr, sizeof(magic)); > > Need a size check before assuming sufficient length. (All of the arm > probe functions suffer in a similar way.) Are you sure? kernel_zimage{32,64}_probe as long as kernel_uboot_probe are checking the size before copying the magic... Regards, -- Julien Grall ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2015-08-13 10:27 UTC | newest] Thread overview: 20+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-08-12 14:47 [PATCH 0/2] support compressed kernels on ARM64 Stefano Stabellini 2015-08-12 14:47 ` [PATCH 1/2] xen: move perform_gunzip to common Stefano Stabellini 2015-08-12 15:14 ` Jan Beulich 2015-08-12 16:15 ` Stefano Stabellini 2015-08-13 6:29 ` Jan Beulich 2015-08-13 9:28 ` Stefano Stabellini 2015-08-13 9:57 ` Jan Beulich 2015-08-13 10:17 ` Ian Campbell 2015-08-13 10:27 ` Jan Beulich 2015-08-12 14:47 ` [PATCH 2/2] xen/arm: support compressed kernels Stefano Stabellini 2015-08-12 15:03 ` Ian Campbell 2015-08-12 15:20 ` Julien Grall 2015-08-12 15:22 ` Stefano Stabellini 2015-08-12 15:27 ` Julien Grall 2015-08-12 15:35 ` Jan Beulich 2015-08-12 15:40 ` Stefano Stabellini 2015-08-12 15:43 ` Ian Campbell 2015-08-12 15:09 ` Julien Grall 2015-08-12 16:35 ` Andrew Cooper 2015-08-12 17:00 ` Julien Grall
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).