[PATCH RFC] x86: Add CONFIG_KERNEL_UNCOMPRESSED support

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

 



Support storing the kernel uncompressed for developers who want to quickly
iterate with one-off kernel builds.
Store it in the usual format with a 4-byte length suffix and keep this new
codepath as close as possible to the normal path where decompression
happens.

The other compression methods offered by the kernel take some time;
even LZ4 (which the kernel uses at compression level 9) takes ~2.8
seconds to compress a 110M large vmlinux.bin on my machine.

An alternate approach to this would be to offer customization of the LZ4
compression level through a kconfig variable; and yet another approach
would be to abuse the existing gzip decompression logic by storing the
kernel as "non-compressed" DEFLATE blocks, so that the decompression code
will essentially end up just doing a bunch of memcpy() calls.

Signed-off-by: Jann Horn <jannh@xxxxxxxxxx>
---
 arch/x86/Kconfig                     |  1 +
 arch/x86/boot/compressed/Makefile    |  3 +++
 arch/x86/boot/compressed/misc.c      |  4 ++++
 arch/x86/boot/header.S               |  2 ++
 drivers/firmware/efi/libstub/zboot.c |  2 ++
 lib/decompress_dummy.c               | 15 +++++++++++++++
 scripts/Makefile.lib                 |  3 +++
 7 files changed, 30 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ef6cfea9df7333c52e331f487a0b29f037a6bf14..6d468d47861ae0b6ec6b7649af6ab4dd123eb5c8 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -250,6 +250,7 @@ config X86
 	select HAVE_KERNEL_LZO
 	select HAVE_KERNEL_XZ
 	select HAVE_KERNEL_ZSTD
+	select HAVE_KERNEL_UNCOMPRESSED
 	select HAVE_KPROBES
 	select HAVE_KPROBES_ON_FTRACE
 	select HAVE_FUNCTION_ERROR_INJECTION
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index f2051644de9432e3466ac0ef1c4d3abc378e37d3..06079e02d9e01704cc0da06c1195854c8d0602ac 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -137,6 +137,8 @@ $(obj)/vmlinux.bin.lz4: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,lz4_with_size)
 $(obj)/vmlinux.bin.zst: $(vmlinux.bin.all-y) FORCE
 	$(call if_changed,zstd22_with_size)
+$(obj)/vmlinux.bin.store: $(vmlinux.bin.all-y) FORCE
+	$(call if_changed,store_with_size)
 
 suffix-$(CONFIG_KERNEL_GZIP)	:= gz
 suffix-$(CONFIG_KERNEL_BZIP2)	:= bz2
@@ -145,6 +147,7 @@ suffix-$(CONFIG_KERNEL_XZ)	:= xz
 suffix-$(CONFIG_KERNEL_LZO) 	:= lzo
 suffix-$(CONFIG_KERNEL_LZ4) 	:= lz4
 suffix-$(CONFIG_KERNEL_ZSTD)	:= zst
+suffix-$(CONFIG_KERNEL_UNCOMPRESSED)	:= store
 
 quiet_cmd_mkpiggy = MKPIGGY $@
       cmd_mkpiggy = $(obj)/mkpiggy $< > $@
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 0d37420cad0259554f8160dea0c502cb7e2fc6cd..5d514a147d5d1ae252419e4c7cdc09e9c29f110f 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -88,6 +88,10 @@ static int cols __section(".data");
 #ifdef CONFIG_KERNEL_ZSTD
 #include "../../../../lib/decompress_unzstd.c"
 #endif
+
+#ifdef CONFIG_KERNEL_UNCOMPRESSED
+#include "../../../../lib/decompress_dummy.c"
+#endif
 /*
  * NOTE: When adding a new decompressor, please update the analysis in
  * ../header.S.
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index b5c79f43359bcde2c4c3c5ed796e8780f7979774..8397470231cf571a33ac75f7ca7020608e170eef 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -483,6 +483,8 @@ pref_address:		.quad LOAD_PHYSICAL_ADDR	# preferred load addr
 # larger margin.
 #
 # extra_bytes = (uncompressed_size >> 8) + 131072
+#
+# Uncompressed data does not grow.
 
 #define ZO_z_extra_bytes	((ZO_z_output_len >> 8) + 131072)
 #if ZO_z_output_len > ZO_z_input_len
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index af23b3c502282f9bd644c38af445875c225cdf42..1c43a6ae5e665aa3bff3bd467c8a2f5525b1a6e9 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c
@@ -27,6 +27,8 @@ static unsigned long free_mem_ptr, free_mem_end_ptr;
 #include "../../../../lib/decompress_unxz.c"
 #elif defined(CONFIG_KERNEL_ZSTD)
 #include "../../../../lib/decompress_unzstd.c"
+#elif defined(CONFIG_KERNEL_UNCOMPRESSED)
+#include "../../../../lib/decompress_dummy.c"
 #endif
 
 extern char efi_zboot_header[];
diff --git a/lib/decompress_dummy.c b/lib/decompress_dummy.c
new file mode 100644
index 0000000000000000000000000000000000000000..49435e199a07f6ed376ff93adeae8ee08a9dd3d7
--- /dev/null
+++ b/lib/decompress_dummy.c
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+STATIC int INIT __decompress(unsigned char *buf, long len,
+			   long (*fill)(void*, unsigned long),
+			   long (*flush)(void*, unsigned long),
+			   unsigned char *out_buf, long out_len,
+			   long *pos,
+			   void (*error)(char *x))
+{
+	if (out_len < len-4) {
+		error("output buffer too small");
+		return -1;
+	}
+	memcpy(out_buf, buf, len-4);
+	return 0;
+}
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 7395200538da89a2f6e6d21f8959f3f60d291d79..bb8116ba8ba189d5246fcb0e71c7be6e05ce5148 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -525,6 +525,9 @@ quiet_cmd_zstd22 = ZSTD22  $@
 quiet_cmd_zstd22_with_size = ZSTD22  $@
       cmd_zstd22_with_size = { cat $(real-prereqs) | $(ZSTD) -22 --ultra; $(size_append); } > $@
 
+quiet_cmd_store_with_size = STORE  $@
+      cmd_store_with_size = { cat $(real-prereqs); $(size_append); } > $@
+
 # ASM offsets
 # ---------------------------------------------------------------------------
 

---
base-commit: 95ec54a420b8f445e04a7ca0ea8deb72c51fe1d3
change-id: 20250121-kernel-compress-fast-350ce5801c28

-- 
Jann Horn <jannh@xxxxxxxxxx>





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux