diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2024-03-18 19:48:12 +0200 |
---|---|---|
committer | Lasse Collin <lasse.collin@tukaani.org> | 2024-03-20 19:01:45 +0200 |
commit | 75d7052e93e4b0bd557d3061557a9e1a91dccf0b (patch) | |
tree | c330df4ed7828de8ef163538e3260863a036eabc | |
parent | 5f391237761ecaa43b45f6eb4daf366416572f7e (diff) | |
download | xz-embedded-75d7052e93e4b0bd557d3061557a9e1a91dccf0b.tar.gz |
xz_wrap.sh: Adjust arch-specific options for better 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 %. 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. On ARM64 the compressed
kernel size is reduced about 5 % and on RISC-V by 7-8 %. These require
new enough version of the xz tool. With an old xz version a message is
printed to standard error and compression is done without the filter.
Update lib/decompress_unxz.c to match the changes to xz_wrap.sh.
Thanks to Jubin Zhong for pointing out that CONFIG_THUMB2_KERNEL
should be used to detect which BCJ filter is used on 32-bit ARM.
https://lore.kernel.org/lkml/1637379771-39449-1-git-send-email-zhongjubin@huawei.com/
It never got merged into Linux. That patch sourced the whole auto.conf
file as a shell script instead of using grep like is done in this commit.
-rw-r--r-- | linux/lib/decompress_unxz.c | 14 | ||||
-rwxr-xr-x | linux/scripts/xz_wrap.sh | 141 |
2 files changed, 148 insertions, 7 deletions
diff --git a/linux/lib/decompress_unxz.c b/linux/lib/decompress_unxz.c index 46aa3be..cae0039 100644 --- a/linux/lib/decompress_unxz.c +++ b/linux/lib/decompress_unxz.c @@ -126,11 +126,21 @@ #ifdef CONFIG_X86 # define XZ_DEC_X86 #endif -#ifdef CONFIG_PPC +#if defined(CONFIG_PPC) && defined(CONFIG_CPU_BIG_ENDIAN) # define XZ_DEC_POWERPC #endif #ifdef CONFIG_ARM -# define XZ_DEC_ARM +# ifdef CONFIG_THUMB2_KERNEL +# define XZ_DEC_ARMTHUMB +# else +# define XZ_DEC_ARM +# endif +#endif +#ifdef CONFIG_ARM64 +# define XZ_DEC_ARM64 +#endif +#ifdef CONFIG_RISCV +# define XZ_DEC_RISCV #endif #ifdef CONFIG_SPARC # define XZ_DEC_SPARC diff --git a/linux/scripts/xz_wrap.sh b/linux/scripts/xz_wrap.sh index c8c3644..5bdf0c3 100755 --- a/linux/scripts/xz_wrap.sh +++ b/linux/scripts/xz_wrap.sh @@ -6,14 +6,145 @@ # # Author: Lasse Collin <lasse.collin@tukaani.org> +# This has specialized settings for the following archs. However, +# XZ-compressed kernel isn't currently supported on every listed arch. +# +# Arch Align Notes +# arm 2/4 ARM and ARM-Thumb2 +# arm64 4 +# csky 2 +# loongarch 4 +# mips 2/4 MicroMIPS is 2-byte aligned +# parisc 4 +# powerpc 4 Uses its own wrapper for compressors instead of this. +# riscv 2/4 +# s390 2 +# sh 2 +# sparc 4 +# x86 1 + +# A few archs use 2-byte or 4-byte aligned instructions depending on +# the kernel config. This function is used to check if the relevant +# config option is set to "y". +is_enabled() +{ + grep -q "^$1=y$" include/config/auto.conf +} + +# Set XZ_VERSION (and LIBLZMA_VERSION). This is needed to disable features +# that aren't available in old XZ Utils versions. +eval "$($XZ --robot --version)" || exit + +# Assume that no BCJ filter is available. BCJ= -LZMA2OPTS= +# Set the instruction alignment to 1, 2, or 4 bytes. +# +# Set the BCJ filter if one is available. +# It must match the #ifdef usage in lib/decompress_unxz.c. case $SRCARCH in - x86) BCJ=--x86 ;; - powerpc) BCJ=--powerpc ;; - arm) BCJ=--arm ;; - sparc) BCJ=--sparc ;; + arm) + if is_enabled CONFIG_THUMB2_KERNEL; then + ALIGN=2 + BCJ=--armthumb + else + ALIGN=4 + BCJ=--arm + fi + ;; + + arm64) + ALIGN=4 + + # ARM64 filter was added in XZ Utils 5.4.0. + if [ "$XZ_VERSION" -ge 50040002 ]; then + BCJ=--arm64 + else + echo "$0: Upgrading to xz >= 5.4.0" \ + "would enable the ARM64 filter" \ + "for better compression" >&2 + fi + ;; + + csky) + ALIGN=2 + ;; + + loongarch) + ALIGN=4 + ;; + + mips) + if is_enabled CONFIG_CPU_MICROMIPS; then + ALIGN=2 + else + ALIGN=4 + fi + ;; + + parisc) + ALIGN=4 + ;; + + powerpc) + ALIGN=4 + + # The filter is only for big endian instruction encoding. + if is_enabled CONFIG_CPU_BIG_ENDIAN; then + BCJ=--powerpc + fi + ;; + + riscv) + if is_enabled CONFIG_RISCV_ISA_C; then + ALIGN=2 + else + ALIGN=4 + fi + + # RISC-V filter was added in XZ Utils 5.6.0. + if [ "$XZ_VERSION" -ge 50060002 ]; then + BCJ=--riscv + else + echo "$0: Upgrading to xz >= 5.6.0" \ + "would enable the RISC-V filter" \ + "for better compression" >&2 + fi + ;; + + s390) + ALIGN=2 + ;; + + sh) + ALIGN=2 + ;; + + sparc) + ALIGN=4 + BCJ=--sparc + ;; + + x86) + ALIGN=1 + BCJ=--x86 + ;; + + *) + echo "$0: Arch-specific tuning is missing for '$SRCARCH'" >&2 + + # Guess 2-byte-aligned instructions. Guessing too low + # should hurt less than guessing too high. + ALIGN=2 + ;; +esac + +# Select the LZMA2 options matching the instruction alignment. +case $ALIGN in + 1) LZMA2OPTS= ;; + 2) LZMA2OPTS=lp=1 ;; + 4) LZMA2OPTS=lp=2,lc=2 ;; + *) echo "$0: ALIGN wrong or missing" >&2; exit 1 ;; esac # Use single-threaded mode because it compresses a little better |