2020-08-05 23:07:31

by Norbert Lange

[permalink] [raw]
Subject: [PATCH] arm: Add support for ZSTD compressed kernel

* Add support for zstd compressed kernel
* Define __DISABLE_EXPORTS in Makefile
* Bump the heap size for zstd.

This replicates the steps taken for x86 support.

Only if ZSTD is selected, heap size for kernel decompression is
increased, this should guarantee no changes in code / sideeffects for
other compressors.

The patch is so far only tested with Qemu, and some 64MB size limit
exists (might be Qemu specific), but this seems not caused by
this patch (upstream 5.8 and GZIP exhibits similar problems).

Signed-off-by: Norbert Lange <[email protected]>
---
arch/arm/Kconfig | 1 +
arch/arm/boot/compressed/Makefile | 2 ++
arch/arm/boot/compressed/decompress.c | 4 ++++
arch/arm/boot/compressed/head.S | 4 ++++
4 files changed, 11 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2ac74904a3ce..3e853cdc688d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -93,6 +93,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_MOD_ARCH_SPECIFIC
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 00602a6fba04..61229e93ea4a 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -75,6 +75,7 @@ compress-$(CONFIG_KERNEL_LZO) = lzo
compress-$(CONFIG_KERNEL_LZMA) = lzma
compress-$(CONFIG_KERNEL_XZ) = xzkern
compress-$(CONFIG_KERNEL_LZ4) = lz4
+compress-$(CONFIG_KERNEL_ZSTD) = zstd22

libfdt_objs := fdt_rw.o fdt_ro.o fdt_wip.o fdt.o

@@ -102,6 +103,7 @@ targets := vmlinux vmlinux.lds piggy_data piggy.o \
clean-files += piggy_data lib1funcs.S ashldi3.S bswapsdi2.S hyp-stub.S

KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
+KBUILD_CFLAGS += -D__DISABLE_EXPORTS

ifeq ($(CONFIG_FUNCTION_TRACER),y)
ORIG_CFLAGS := $(KBUILD_CFLAGS)
diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c
index aa075d8372ea..04f77491975a 100644
--- a/arch/arm/boot/compressed/decompress.c
+++ b/arch/arm/boot/compressed/decompress.c
@@ -56,6 +56,10 @@ extern char * strchrnul(const char *, int);
#include "../../../../lib/decompress_unlz4.c"
#endif

+#ifdef CONFIG_KERNEL_ZSTD
+#include "../../../../lib/decompress_unzstd.c"
+#endif
+
int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
{
return __decompress(input, len, NULL, NULL, output, 0, NULL, error);
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 434a16982e34..1af01bfe6638 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -614,7 +614,11 @@ not_relocated: mov r0, #0
*/
mov r0, r4
mov r1, sp @ malloc space above stack
+#if defined(CONFIG_KERNEL_ZSTD)
+ add r2, sp, #0x30000 @ Context needs ~160K
+#else
add r2, sp, #0x10000 @ 64k max
+#endif
mov r3, r7
bl decompress_kernel

--
2.27.0


2020-08-06 00:32:29

by Russell King (Oracle)

[permalink] [raw]
Subject: Re: [PATCH] arm: Add support for ZSTD compressed kernel

On Thu, Aug 06, 2020 at 01:05:55AM +0200, Norbert Lange wrote:
> diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> index 434a16982e34..1af01bfe6638 100644
> --- a/arch/arm/boot/compressed/head.S
> +++ b/arch/arm/boot/compressed/head.S
> @@ -614,7 +614,11 @@ not_relocated: mov r0, #0
> */
> mov r0, r4
> mov r1, sp @ malloc space above stack
> +#if defined(CONFIG_KERNEL_ZSTD)
> + add r2, sp, #0x30000 @ Context needs ~160K

That's going to mess up kexec:

/*
* The zImage length does not include its stack (4k) or its
* malloc space (64k). Include this.
*/
len += 0x11000;

I guess we need to add this to the information provided to kexec.

--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

2020-08-06 08:46:38

by Norbert Lange

[permalink] [raw]
Subject: Re: [PATCH] arm: Add support for ZSTD compressed kernel

Am Do., 6. Aug. 2020 um 02:30 Uhr schrieb Russell King - ARM Linux
admin <[email protected]>:
>
> On Thu, Aug 06, 2020 at 01:05:55AM +0200, Norbert Lange wrote:
> > diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> > index 434a16982e34..1af01bfe6638 100644
> > --- a/arch/arm/boot/compressed/head.S
> > +++ b/arch/arm/boot/compressed/head.S
> > @@ -614,7 +614,11 @@ not_relocated: mov r0, #0
> > */
> > mov r0, r4
> > mov r1, sp @ malloc space above stack
> > +#if defined(CONFIG_KERNEL_ZSTD)
> > + add r2, sp, #0x30000 @ Context needs ~160K
>
> That's going to mess up kexec:
>
> /*
> * The zImage length does not include its stack (4k) or its
> * malloc space (64k). Include this.
> */
> len += 0x11000;
>
> I guess we need to add this to the information provided to kexec.

Ouch, I guess it's rather impossible to load a new ZSTD kernel with a old
kexec version in that case.

Some ideas to fix that would be:

- Increase the padding to "192K + 4K is enough for everyone" in kexec
- Add the required/recommended stack+heap size to zImage so kexec can use it.
- change boot logic to place heap before/after the *output* range.
with the various ways of booting arm this will likely cause other
issues in some combinations.
- try to reduce zstd context size safetly below 64K.
I believe the entropy tables are computed once and never modified,
so those could be part of the zImage
(at some loss of compression rate of course). Would need some host
tool to inject those.

Norbert

2020-08-06 10:13:09

by Russell King (Oracle)

[permalink] [raw]
Subject: Re: [PATCH] arm: Add support for ZSTD compressed kernel

On Thu, Aug 06, 2020 at 10:45:42AM +0200, Norbert Lange wrote:
> Am Do., 6. Aug. 2020 um 02:30 Uhr schrieb Russell King - ARM Linux
> admin <[email protected]>:
> >
> > On Thu, Aug 06, 2020 at 01:05:55AM +0200, Norbert Lange wrote:
> > > diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
> > > index 434a16982e34..1af01bfe6638 100644
> > > --- a/arch/arm/boot/compressed/head.S
> > > +++ b/arch/arm/boot/compressed/head.S
> > > @@ -614,7 +614,11 @@ not_relocated: mov r0, #0
> > > */
> > > mov r0, r4
> > > mov r1, sp @ malloc space above stack
> > > +#if defined(CONFIG_KERNEL_ZSTD)
> > > + add r2, sp, #0x30000 @ Context needs ~160K
> >
> > That's going to mess up kexec:
> >
> > /*
> > * The zImage length does not include its stack (4k) or its
> > * malloc space (64k). Include this.
> > */
> > len += 0x11000;
> >
> > I guess we need to add this to the information provided to kexec.
>
> Ouch, I guess it's rather impossible to load a new ZSTD kernel with a old
> kexec version in that case.
>
> Some ideas to fix that would be:
>
> - Increase the padding to "192K + 4K is enough for everyone" in kexec
> - Add the required/recommended stack+heap size to zImage so kexec can use it.

This is definitely preferred. See patches - though this is only the
kernel side. The first I've had for some time and isn't related to
this issue.

--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

2020-08-06 10:14:32

by Russell King (Oracle)

[permalink] [raw]
Subject: [PATCH 2/2] ARM: add malloc size to decompressor kexec size structure

Add the required malloc size to the decompressor kexec size structure.

Signed-off-by: Russell King <[email protected]>
---
arch/arm/boot/compressed/Makefile | 5 ++++-
arch/arm/boot/compressed/head.S | 4 ++--
arch/arm/boot/compressed/vmlinux.lds.S | 3 ++-
3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 0890d82b8cf4..432af49ddbcb 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -7,7 +7,6 @@

OBJS =

-AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
HEAD = head.o
OBJS += misc.o decompress.o
ifeq ($(CONFIG_DEBUG_UNCOMPRESS),y)
@@ -69,8 +68,12 @@ ZTEXTADDR := 0
ZBSSADDR := ALIGN(8)
endif

+MALLOC_SIZE := 65536
+
+AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) -DMALLOC_SIZE=$(MALLOC_SIZE)
CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)"
CPPFLAGS_vmlinux.lds += -DTEXT_OFFSET="$(TEXT_OFFSET)"
+CPPFLAGS_vmlinux.lds += -DMALLOC_SIZE="$(MALLOC_SIZE)"

compress-$(CONFIG_KERNEL_GZIP) = gzip
compress-$(CONFIG_KERNEL_LZO) = lzo
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 7f24f0852a94..2ea4521bf7df 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -299,7 +299,7 @@ restart: adr r0, LC1

#ifndef CONFIG_ZBOOT_ROM
/* malloc space is above the relocated stack (64k max) */
- add r10, sp, #0x10000
+ add r10, sp, #MALLOC_SIZE
#else
/*
* With ZBOOT_ROM the bss/stack is non relocatable,
@@ -610,7 +610,7 @@ not_relocated: mov r0, #0
*/
mov r0, r4
mov r1, sp @ malloc space above stack
- add r2, sp, #0x10000 @ 64k max
+ add r2, sp, #MALLOC_SIZE @ 64k max
mov r3, r7
bl decompress_kernel

diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S
index da1f6fa5345b..0ed4d82d3782 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -42,11 +42,12 @@ SECTIONS
}
.table : ALIGN(4) {
_table_start = .;
- LONG(ZIMAGE_MAGIC(5))
+ LONG(ZIMAGE_MAGIC(6))
LONG(ZIMAGE_MAGIC(0x5a534c4b))
LONG(ZIMAGE_MAGIC(__piggy_size_addr - _start))
LONG(ZIMAGE_MAGIC(_kernel_bss_size))
LONG(ZIMAGE_MAGIC(TEXT_OFFSET))
+ LONG(ZIMAGE_MAGIC(MALLOC_SIZE))
LONG(0)
_table_end = .;
}
--
2.20.1

2020-08-06 10:15:43

by Russell King (Oracle)

[permalink] [raw]
Subject: [PATCH 1/2] ARM: add TEXT_OFFSET to decompressor kexec image structure

Add the TEXT_OFFSET to the decompressor's kexec image structure to
kexec knows what offset to use.

Signed-off-by: Russell King <[email protected]>
---
arch/arm/Makefile | 3 +++
arch/arm/boot/compressed/Makefile | 1 +
arch/arm/boot/compressed/vmlinux.lds.S | 3 ++-
3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 01ed27a538b4..ab2d66e40b7f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -139,6 +139,9 @@ head-y := arch/arm/kernel/head$(MMUEXT).o

# Text offset. This list is sorted numerically by address in order to
# provide a means to avoid/resolve conflicts in multi-arch kernels.
+# Note: the 32kB below this value is reserved for use by the kernel
+# during boot, and this offset is critical to the functioning of
+# kexec-tools.
textofs-y := 0x00008000
# We don't want the htc bootloader to corrupt kernel during resume
textofs-$(CONFIG_PM_H1940) := 0x00108000
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 433fb7f04aa5..0890d82b8cf4 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -70,6 +70,7 @@ ZBSSADDR := ALIGN(8)
endif

CPPFLAGS_vmlinux.lds := -DTEXT_START="$(ZTEXTADDR)" -DBSS_START="$(ZBSSADDR)"
+CPPFLAGS_vmlinux.lds += -DTEXT_OFFSET="$(TEXT_OFFSET)"

compress-$(CONFIG_KERNEL_GZIP) = gzip
compress-$(CONFIG_KERNEL_LZO) = lzo
diff --git a/arch/arm/boot/compressed/vmlinux.lds.S b/arch/arm/boot/compressed/vmlinux.lds.S
index 09ac33f52814..da1f6fa5345b 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -42,10 +42,11 @@ SECTIONS
}
.table : ALIGN(4) {
_table_start = .;
- LONG(ZIMAGE_MAGIC(4))
+ LONG(ZIMAGE_MAGIC(5))
LONG(ZIMAGE_MAGIC(0x5a534c4b))
LONG(ZIMAGE_MAGIC(__piggy_size_addr - _start))
LONG(ZIMAGE_MAGIC(_kernel_bss_size))
+ LONG(ZIMAGE_MAGIC(TEXT_OFFSET))
LONG(0)
_table_end = .;
}
--
2.20.1