linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] ARM ZSTD boot compression
@ 2026-08-28 20:32 Andreas Kemnade
  2026-08-28 20:32 ` [PATCH v2 1/3] ARM: compressed: Pass the actual output length to the decompressor Andreas Kemnade
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Andreas Kemnade @ 2026-08-28 20:32 UTC (permalink / raw)
  To: Russell King, Nick Terrell, David Sterba, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt
  Cc: Andreas Kemnade, j.neuschaefer, f.fainelli, Tony Lindgren,
	linux-arm-kernel, linux-kernel, Linus Walleij

Add ZSTD compression to still have a quite high compression but with
not too much boot delay penality. 

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
Changes in v2:
- rebased
- practically rewritten 3/3 (and therefore changed author)
- added more measurements
- Link to v1: https://lore.kernel.org/lkml/ZDoDYh01GYjdwp63@probook/

To: Russell King <linux@armlinux.org.uk>
To: Nick Terrell <terrelln@fb.com>
To: David Sterba <dsterba@suse.com>
To: Nathan Chancellor <nathan@kernel.org>
To: Nick Desaulniers <ndesaulniers@google.com>
To: Bill Wendling <morbo@google.com>
To: Justin Stitt <justinstitt@google.com>
Cc: j.neuschaefer@gmx.net
Cc: f.fainelli@gmail.com
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Tony Lindgren <tony@atomide.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org

---
Andreas Kemnade (1):
      ARM: compressed: Enable ZSTD compression

Jonathan Neuschäfer (2):
      ARM: compressed: Pass the actual output length to the decompressor
      ARM: compressed: Bump MALLOC_SIZE to 128 KiB

 arch/arm/Kconfig                      |  1 +
 arch/arm/boot/compressed/Makefile     |  3 ++-
 arch/arm/boot/compressed/decompress.c | 15 ++++++++++++---
 arch/arm/boot/compressed/head.S       |  4 ++--
 arch/arm/boot/compressed/misc.c       | 10 +++++++++-
 arch/arm/boot/compressed/misc.h       |  3 ++-
 6 files changed, 28 insertions(+), 8 deletions(-)
---
base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
change-id: 20260828-zstd2-045ce924f624

Best regards,
--  
Andreas Kemnade <andreas@kemnade.info>



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2 1/3] ARM: compressed: Pass the actual output length to the decompressor
  2026-08-28 20:32 [PATCH v2 0/3] ARM ZSTD boot compression Andreas Kemnade
@ 2026-08-28 20:32 ` Andreas Kemnade
  2026-08-28 20:32 ` [PATCH v2 2/3] ARM: compressed: Bump MALLOC_SIZE to 128 KiB Andreas Kemnade
  2026-08-28 20:32 ` [PATCH v2 3/3] ARM: compressed: Enable ZSTD compression Andreas Kemnade
  2 siblings, 0 replies; 4+ messages in thread
From: Andreas Kemnade @ 2026-08-28 20:32 UTC (permalink / raw)
  To: Russell King, Nick Terrell, David Sterba, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt
  Cc: Andreas Kemnade, j.neuschaefer, f.fainelli, Tony Lindgren,
	linux-arm-kernel, linux-kernel, Linus Walleij

From: Jonathan Neuschäfer <j.neuschaefer@gmx.net>

ZSTD writes outside of the space that is necessary for the uncompressed
data, when it is told it has unlimited output length. To fix this, pass
the actual output length (the length of the uncompressed kernel) to the
decompressor.

The uncompressed length is already stored as a little endian 32-bit
constant before the input_data_end symbol.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Reviewed-by: Tony Lindgren <tony@atomide.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
 arch/arm/boot/compressed/decompress.c |  4 ++--
 arch/arm/boot/compressed/misc.c       | 10 +++++++++-
 arch/arm/boot/compressed/misc.h       |  3 ++-
 3 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
index 0669851394f04..b0352f379277f 100644
--- a/arch/arm/boot/compressed/decompress.c
+++ b/arch/arm/boot/compressed/decompress.c
@@ -60,7 +60,7 @@ extern char * strchrnul(const char *, int);
 #include "../../../../lib/decompress_unlz4.c"
 #endif
 
-int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
+int do_decompress(u8 *input, int len, u8 *output, int outlen, void (*error)(char *x))
 {
-	return __decompress(input, len, NULL, NULL, output, 0, NULL, error);
+	return __decompress(input, len, NULL, NULL, output, outlen, NULL, error);
 }
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index 6c41b270560e1..58826885ccc82 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -22,6 +22,7 @@ unsigned int __machine_arch_type;
 #include <linux/compiler.h>	/* for inline */
 #include <linux/types.h>
 #include <linux/linkage.h>
+#include <linux/unaligned.h>
 #include "misc.h"
 #ifdef CONFIG_ARCH_EP93XX
 #include "misc-ep93xx.h"
@@ -128,14 +129,21 @@ asmlinkage void __div0(void)
 	error("Attempting division by 0!");
 }
 
+static u32 get_inflated_image_size(void)
+{
+	return get_unaligned_le32(input_data_end - 4);
+}
+
 void
 decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
 		unsigned long free_mem_ptr_end_p,
 		int arch_id)
 {
+	unsigned long output_data_len;
 	int ret;
 
 	output_data		= (unsigned char *)output_start;
+	output_data_len         = get_inflated_image_size();
 	free_mem_ptr		= free_mem_ptr_p;
 	free_mem_end_ptr	= free_mem_ptr_end_p;
 	__machine_arch_type	= arch_id;
@@ -147,7 +155,7 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
 
 	putstr("Uncompressing Linux...");
 	ret = do_decompress(input_data, input_data_end - input_data,
-			    output_data, error);
+			    output_data, output_data_len, error);
 	if (ret)
 		error("decompressor returned an error");
 	else
diff --git a/arch/arm/boot/compressed/misc.h b/arch/arm/boot/compressed/misc.h
index 8c73940b5fe46..ec8de2388f0ec 100644
--- a/arch/arm/boot/compressed/misc.h
+++ b/arch/arm/boot/compressed/misc.h
@@ -13,7 +13,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
 void __fortify_panic(const u8 reason, size_t avail, size_t size);
 int atags_to_fdt(void *atag_list, void *fdt, int total_space);
 uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt);
-int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
+int do_decompress(u8 *input, int len, u8 *output, int outlen,
+		  void (*error)(char *x));
 
 extern char input_data[];
 extern char input_data_end[];

-- 
2.47.3



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/3] ARM: compressed: Bump MALLOC_SIZE to 128 KiB
  2026-08-28 20:32 [PATCH v2 0/3] ARM ZSTD boot compression Andreas Kemnade
  2026-08-28 20:32 ` [PATCH v2 1/3] ARM: compressed: Pass the actual output length to the decompressor Andreas Kemnade
@ 2026-08-28 20:32 ` Andreas Kemnade
  2026-08-28 20:32 ` [PATCH v2 3/3] ARM: compressed: Enable ZSTD compression Andreas Kemnade
  2 siblings, 0 replies; 4+ messages in thread
From: Andreas Kemnade @ 2026-08-28 20:32 UTC (permalink / raw)
  To: Russell King, Nick Terrell, David Sterba, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt
  Cc: Andreas Kemnade, j.neuschaefer, f.fainelli, Tony Lindgren,
	linux-arm-kernel, linux-kernel, Linus Walleij

From: Jonathan Neuschäfer <j.neuschaefer@gmx.net>

The ZSTD compressor needs about 100 KiB.

Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
 arch/arm/boot/compressed/Makefile | 2 +-
 arch/arm/boot/compressed/head.S   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index e3f550d628578..fa6ee23cd72eb 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -62,7 +62,7 @@ ZTEXTADDR	:= 0
 ZBSSADDR	:= ALIGN(8)
 endif
 
-MALLOC_SIZE	:= 65536
+MALLOC_SIZE	:= 131072
 
 AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) -DMALLOC_SIZE=$(MALLOC_SIZE)
 CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)"
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 9f406e9c0ea6f..23fbbe94da6e8 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -337,7 +337,7 @@ restart:	adr	r0, LC1
 		get_inflated_image_size	r9, r10, lr
 
 #ifndef CONFIG_ZBOOT_ROM
-		/* malloc space is above the relocated stack (64k max) */
+		/* malloc space is above the relocated stack (128k max) */
 		add	r10, sp, #MALLOC_SIZE
 #else
 		/*
@@ -629,7 +629,7 @@ not_relocated:	mov	r0, #0
  */
 		mov	r0, r4
 		mov	r1, sp			@ malloc space above stack
-		add	r2, sp, #MALLOC_SIZE	@ 64k max
+		add	r2, sp, #MALLOC_SIZE	@ 128k max
 		mov	r3, r7
 		bl	decompress_kernel
 

-- 
2.47.3



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 3/3] ARM: compressed: Enable ZSTD compression
  2026-08-28 20:32 [PATCH v2 0/3] ARM ZSTD boot compression Andreas Kemnade
  2026-08-28 20:32 ` [PATCH v2 1/3] ARM: compressed: Pass the actual output length to the decompressor Andreas Kemnade
  2026-08-28 20:32 ` [PATCH v2 2/3] ARM: compressed: Bump MALLOC_SIZE to 128 KiB Andreas Kemnade
@ 2026-08-28 20:32 ` Andreas Kemnade
  2 siblings, 0 replies; 4+ messages in thread
From: Andreas Kemnade @ 2026-08-28 20:32 UTC (permalink / raw)
  To: Russell King, Nick Terrell, David Sterba, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt
  Cc: Andreas Kemnade, j.neuschaefer, f.fainelli, Tony Lindgren,
	linux-arm-kernel, linux-kernel, Linus Walleij

With the previous two commits, it is possible to enable ZSTD
in the decompressor stub for 32-bit ARM.

KASAN logic for XZ is extended for ZSTD, since
the affected functions are also in use.

Measurement was done with clang-19.
Setup was: starting a fastboot image via u-boot,
serial console attached.
Time was measured using ts -s %.s </dev/ttyUSBx | tee logfile
from the last words from u-boot still the first
kernel message. No early serial output was in use.

GTA04 (OMAP3) with something based on omap2plus_defconfig:
     zImage size	time
GZIP 7997 KiB		1.6s
LZMA 5794 KiB		4.6s
ZSTD 6774 KiB		2.7s

Tolino Shine 2 HD (i.MX6SL) with something based on imx_v6_v7_defconfig

GZIP 10499 KiB		 0.9s
LZMA 7611 KiB		 3.8s
ZSTD 8884 KiB		 2.0s

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
 arch/arm/Kconfig                      |  1 +
 arch/arm/boot/compressed/Makefile     |  1 +
 arch/arm/boot/compressed/decompress.c | 11 ++++++++++-
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9187240a02db5..cf612ee4064c3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -122,6 +122,7 @@ config ARM
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_LZO
 	select HAVE_KERNEL_XZ
+	select HAVE_KERNEL_ZSTD
 	select HAVE_KPROBES if !XIP_KERNEL && !CPU_ENDIAN_BE32 && !CPU_V7M
 	select HAVE_KRETPROBES if HAVE_KPROBES
 	select HAVE_LD_DEAD_CODE_DATA_ELIMINATION if (LD_VERSION >= 23600 || LD_IS_LLD) && LD_CAN_USE_KEEP_IN_OVERLAY
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index fa6ee23cd72eb..1c6638e1999ab 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -74,6 +74,7 @@ compress-$(CONFIG_KERNEL_LZO)  = lzo_with_size
 compress-$(CONFIG_KERNEL_LZMA) = lzma_with_size
 compress-$(CONFIG_KERNEL_XZ)   = xzkern_with_size
 compress-$(CONFIG_KERNEL_LZ4)  = lz4_with_size
+compress-$(CONFIG_KERNEL_ZSTD)  = zstd22_with_size
 
 libfdt_objs := fdt_rw.o fdt_ro.o fdt_wip.o fdt.o
 
diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
index b0352f379277f..5f82c0c754fa5 100644
--- a/arch/arm/boot/compressed/decompress.c
+++ b/arch/arm/boot/compressed/decompress.c
@@ -47,15 +47,24 @@ extern char * strchrnul(const char *, int);
 #include "../../../../lib/decompress_unlzma.c"
 #endif
 
-#ifdef CONFIG_KERNEL_XZ
+#if defined(CONFIG_KERNEL_XZ) || defined(CONFIG_KERNEL_ZSTD)
 /* Prevent KASAN override of string helpers in decompressor */
 #undef memmove
 #define memmove memmove
 #undef memcpy
 #define memcpy memcpy
+#undef memset
+#define memset memset
+#endif
+
+#ifdef CONFIG_KERNEL_XZ
 #include "../../../../lib/decompress_unxz.c"
 #endif
 
+#ifdef CONFIG_KERNEL_ZSTD
+#include "../../../../lib/decompress_unzstd.c"
+#endif
+
 #ifdef CONFIG_KERNEL_LZ4
 #include "../../../../lib/decompress_unlz4.c"
 #endif

-- 
2.47.3



^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-08-28 20:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-28 20:32 [PATCH v2 0/3] ARM ZSTD boot compression Andreas Kemnade
2026-08-28 20:32 ` [PATCH v2 1/3] ARM: compressed: Pass the actual output length to the decompressor Andreas Kemnade
2026-08-28 20:32 ` [PATCH v2 2/3] ARM: compressed: Bump MALLOC_SIZE to 128 KiB Andreas Kemnade
2026-08-28 20:32 ` [PATCH v2 3/3] ARM: compressed: Enable ZSTD compression Andreas Kemnade

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).