Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xz: adjust arch-specific options for better kernel compression

Use LZMA2 options that match the arch-specific alignment of instructions.
This change reduces compressed kernel size 0-2 % depending on the arch.
On 1-byte-aligned x86 it makes no difference and on 4-byte-aligned archs
it helps the most.

Use the ARM-Thumb filter for ARM-Thumb2 kernels. This reduces compressed
kernel size about 5 %.[1] Previously such kernels were compressed using
the ARM filter which didn't do anything useful with ARM-Thumb2 code.

Add BCJ filter support for ARM64 and RISC-V. Compared to unfiltered XZ or
plain LZMA, the compressed kernel size is reduced about 5 % on ARM64 and 7
% on RISC-V. A new enough version of the xz tool is required: 5.4.0 for
ARM64 and 5.6.0 for RISC-V. With an old xz version, a message is printed
to standard error and the kernel is compressed without the filter.

Update lib/decompress_unxz.c to match the changes to xz_wrap.sh.

Update the CONFIG_KERNEL_XZ help text in init/Kconfig:
- Add the RISC-V and ARM64 filters.
- Clarify that the PowerPC filter is for big endian only.
- Omit IA-64.

Link: https://lore.kernel.org/lkml/1637379771-39449-1-git-send-email-zhongjubin@huawei.com/ [1]
Link: https://lkml.kernel.org/r/20240721133633.47721-15-lasse.collin@tukaani.org
Signed-off-by: Lasse Collin <lasse.collin@tukaani.org>
Reviewed-by: Sam James <sam@gentoo.org>
Cc: Simon Glass <sjg@chromium.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Paul Walmsley <paul.walmsley@sifive.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Jubin Zhong <zhongjubin@huawei.com>
Cc: Jules Maselbas <jmaselbas@zdiv.net>
Cc: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Joel Stanley <joel@jms.id.au>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Krzysztof Kozlowski <krzk@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Rui Li <me@lirui.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Lasse Collin and committed by
Andrew Morton
7472ff8a 8653c909

+153 -10
+3 -2
init/Kconfig
··· 310 310 BCJ filters which can improve compression ratio of executable 311 311 code. The size of the kernel is about 30% smaller with XZ in 312 312 comparison to gzip. On architectures for which there is a BCJ 313 - filter (i386, x86_64, ARM, IA-64, PowerPC, and SPARC), XZ 314 - will create a few percent smaller kernel than plain LZMA. 313 + filter (i386, x86_64, ARM, ARM64, RISC-V, big endian PowerPC, 314 + and SPARC), XZ will create a few percent smaller kernel than 315 + plain LZMA. 315 316 316 317 The speed is about the same as with LZMA: The decompression 317 318 speed of XZ is better than that of bzip2 but worse than gzip
+12 -2
lib/decompress_unxz.c
··· 126 126 #ifdef CONFIG_X86 127 127 # define XZ_DEC_X86 128 128 #endif 129 - #ifdef CONFIG_PPC 129 + #if defined(CONFIG_PPC) && defined(CONFIG_CPU_BIG_ENDIAN) 130 130 # define XZ_DEC_POWERPC 131 131 #endif 132 132 #ifdef CONFIG_ARM 133 - # define XZ_DEC_ARM 133 + # ifdef CONFIG_THUMB2_KERNEL 134 + # define XZ_DEC_ARMTHUMB 135 + # else 136 + # define XZ_DEC_ARM 137 + # endif 138 + #endif 139 + #ifdef CONFIG_ARM64 140 + # define XZ_DEC_ARM64 141 + #endif 142 + #ifdef CONFIG_RISCV 143 + # define XZ_DEC_RISCV 134 144 #endif 135 145 #ifdef CONFIG_SPARC 136 146 # define XZ_DEC_SPARC
+138 -6
scripts/xz_wrap.sh
··· 6 6 # 7 7 # Author: Lasse Collin <lasse.collin@tukaani.org> 8 8 9 - BCJ= 10 - LZMA2OPTS= 9 + # This has specialized settings for the following archs. However, 10 + # XZ-compressed kernel isn't currently supported on every listed arch. 11 + # 12 + # Arch Align Notes 13 + # arm 2/4 ARM and ARM-Thumb2 14 + # arm64 4 15 + # csky 2 16 + # loongarch 4 17 + # mips 2/4 MicroMIPS is 2-byte aligned 18 + # parisc 4 19 + # powerpc 4 Uses its own wrapper for compressors instead of this. 20 + # riscv 2/4 21 + # s390 2 22 + # sh 2 23 + # sparc 4 24 + # x86 1 11 25 26 + # A few archs use 2-byte or 4-byte aligned instructions depending on 27 + # the kernel config. This function is used to check if the relevant 28 + # config option is set to "y". 29 + is_enabled() 30 + { 31 + grep -q "^$1=y$" include/config/auto.conf 32 + } 33 + 34 + # XZ_VERSION is needed to disable features that aren't available in 35 + # old XZ Utils versions. 36 + XZ_VERSION=$($XZ --robot --version) || exit 37 + XZ_VERSION=$(printf '%s\n' "$XZ_VERSION" | sed -n 's/^XZ_VERSION=//p') 38 + 39 + # Assume that no BCJ filter is available. 40 + BCJ= 41 + 42 + # Set the instruction alignment to 1, 2, or 4 bytes. 43 + # 44 + # Set the BCJ filter if one is available. 45 + # It must match the #ifdef usage in lib/decompress_unxz.c. 12 46 case $SRCARCH in 13 - x86) BCJ=--x86 ;; 14 - powerpc) BCJ=--powerpc ;; 15 - arm) BCJ=--arm ;; 16 - sparc) BCJ=--sparc ;; 47 + arm) 48 + if is_enabled CONFIG_THUMB2_KERNEL; then 49 + ALIGN=2 50 + BCJ=--armthumb 51 + else 52 + ALIGN=4 53 + BCJ=--arm 54 + fi 55 + ;; 56 + 57 + arm64) 58 + ALIGN=4 59 + 60 + # ARM64 filter was added in XZ Utils 5.4.0. 61 + if [ "$XZ_VERSION" -ge 50040002 ]; then 62 + BCJ=--arm64 63 + else 64 + echo "$0: Upgrading to xz >= 5.4.0" \ 65 + "would enable the ARM64 filter" \ 66 + "for better compression" >&2 67 + fi 68 + ;; 69 + 70 + csky) 71 + ALIGN=2 72 + ;; 73 + 74 + loongarch) 75 + ALIGN=4 76 + ;; 77 + 78 + mips) 79 + if is_enabled CONFIG_CPU_MICROMIPS; then 80 + ALIGN=2 81 + else 82 + ALIGN=4 83 + fi 84 + ;; 85 + 86 + parisc) 87 + ALIGN=4 88 + ;; 89 + 90 + powerpc) 91 + ALIGN=4 92 + 93 + # The filter is only for big endian instruction encoding. 94 + if is_enabled CONFIG_CPU_BIG_ENDIAN; then 95 + BCJ=--powerpc 96 + fi 97 + ;; 98 + 99 + riscv) 100 + if is_enabled CONFIG_RISCV_ISA_C; then 101 + ALIGN=2 102 + else 103 + ALIGN=4 104 + fi 105 + 106 + # RISC-V filter was added in XZ Utils 5.6.0. 107 + if [ "$XZ_VERSION" -ge 50060002 ]; then 108 + BCJ=--riscv 109 + else 110 + echo "$0: Upgrading to xz >= 5.6.0" \ 111 + "would enable the RISC-V filter" \ 112 + "for better compression" >&2 113 + fi 114 + ;; 115 + 116 + s390) 117 + ALIGN=2 118 + ;; 119 + 120 + sh) 121 + ALIGN=2 122 + ;; 123 + 124 + sparc) 125 + ALIGN=4 126 + BCJ=--sparc 127 + ;; 128 + 129 + x86) 130 + ALIGN=1 131 + BCJ=--x86 132 + ;; 133 + 134 + *) 135 + echo "$0: Arch-specific tuning is missing for '$SRCARCH'" >&2 136 + 137 + # Guess 2-byte-aligned instructions. Guessing too low 138 + # should hurt less than guessing too high. 139 + ALIGN=2 140 + ;; 141 + esac 142 + 143 + # Select the LZMA2 options matching the instruction alignment. 144 + case $ALIGN in 145 + 1) LZMA2OPTS= ;; 146 + 2) LZMA2OPTS=lp=1 ;; 147 + 4) LZMA2OPTS=lp=2,lc=2 ;; 148 + *) echo "$0: ALIGN wrong or missing" >&2; exit 1 ;; 17 149 esac 18 150 19 151 # Use single-threaded mode because it compresses a little better