[PATCH] ARM: head: Remove 1-2 MiB of pointless padding
Ard Biesheuvel
ardb at kernel.org
Mon May 8 08:44:02 PDT 2023
On Mon, 8 May 2023 at 16:55, Ard Biesheuvel <ardb at kernel.org> wrote:
>
> Currently, some of the early init code is emitted into .head.text, which
> is allocated as a separate section in the linker script, and if
> CONFIG_STRICT_KERNEL_RWX=y, which is the default, the .text section that
> follows it is aligned to a section mapping boundary, i.e., 1 MiB or 2 MiB,
> depending on whether or not LPAE is enabled.
>
> This results in 1 - 2 MiB of space wasted on padding for no good reason:
> the only part of .head.text that really needs special treatment is the
> first instruction (which is the entrypoint), but everything else is
> essentially inittext and can be emitted as such.
>
> So let's remove everything except the initial instruction from
> .head.text, and convert it into a branch to the actual primary startup
> code, which is moved into the .init.text section. That leaves a
> .head.text section of only 4 bytes, which can be placed at the start of
> the ordinary .text section, without any padding or alignment.
>
> While at it, drop the special Thumb switch sequence, and just use a BL
> branch-and-link instruction for the initial jump so that the linker can
> turn it into an interworking BLX instruction as needed. (No interworking
> variant of the ordinary B branch instruction exists, so the linker would
> need to emit a veneer to effectuate the ARM to Thumb mode switch)
>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
Hmm, one thing I seem to have missed is that _text does not currently
start on a section aligned boundary, so making _stext == _text does
not satisfy the alignment constraints of STRICT_KERNEL_RWX
Given that it would only take 1 additional page worth of page tables
to break up this section, I still don't think the padding is
justified, and we should just map the start of .text down to pages.
Or did I miss anything here?
> ---
> arch/arm/kernel/head-common.S | 2 +-
> arch/arm/kernel/head-nommu.S | 14 +++++++-------
> arch/arm/kernel/head.S | 15 ++++++++-------
> arch/arm/kernel/phys2virt.S | 2 +-
> arch/arm/kernel/vmlinux-xip.lds.S | 7 ++-----
> arch/arm/kernel/vmlinux.lds.S | 14 ++------------
> 6 files changed, 21 insertions(+), 33 deletions(-)
>
> diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
> index 42cae73fcc19d016..d01ee2e6a5a37723 100644
> --- a/arch/arm/kernel/head-common.S
> +++ b/arch/arm/kernel/head-common.S
> @@ -27,7 +27,7 @@
> * and hope for the best (useful if bootloader fails to pass a proper
> * machine ID for example).
> */
> - __HEAD
> + __INIT
>
> /* Determine validity of the r2 atags pointer. The heuristic requires
> * that the pointer be aligned, in the first 16k of physical RAM and
> diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
> index 950bef83339f5e5b..434a1ea7b38f2a88 100644
> --- a/arch/arm/kernel/head-nommu.S
> +++ b/arch/arm/kernel/head-nommu.S
> @@ -42,13 +42,13 @@ ENTRY(stext)
> #else
> .arm
> ENTRY(stext)
> -
> - THUMB( badr r9, 1f ) @ Kernel is always entered in ARM.
> - THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
> - THUMB( .thumb ) @ switch to Thumb now.
> - THUMB(1: )
> #endif
> + bl primary_startup @ interworking branch on Thumb
> +ENDPROC(stext)
>
> + __INIT
> + THUMB( .thumb ) @ switch to Thumb now.
> +primary_startup:
> #ifdef CONFIG_ARM_VIRT_EXT
> bl __hyp_stub_install
> #endif
> @@ -77,7 +77,7 @@ ENTRY(stext)
> ret r12
> 1: ldr lr, =__mmap_switched
> b __after_proc_init
> -ENDPROC(stext)
> +ENDPROC(primary_startup)
>
> #ifdef CONFIG_SMP
> .text
> @@ -249,7 +249,7 @@ ENDPROC(__after_proc_init)
> *
> * r6: Value to be written to DRSR (and IRSR if required) for PMSAv7_RAM_REGION
> */
> - __HEAD
> + __INIT
>
> ENTRY(__setup_mpu)
>
> diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
> index 656991055bc17bc4..b56b252b128ffae7 100644
> --- a/arch/arm/kernel/head.S
> +++ b/arch/arm/kernel/head.S
> @@ -91,13 +91,14 @@ kernel_sec_end:
>
> __HEAD
> ENTRY(stext)
> - ARM_BE8(setend be ) @ ensure we are in BE8 mode
> + bl primary_startup @ interworking branch on Thumb
> +ENDPROC(stext)
>
> - THUMB( badr r9, 1f ) @ Kernel is always entered in ARM.
> - THUMB( bx r9 ) @ If this is a Thumb-2 kernel,
> - THUMB( .thumb ) @ switch to Thumb now.
> - THUMB(1: )
> + __INIT
>
> + THUMB( .thumb ) @ switch to Thumb now.
> +primary_startup:
> + ARM_BE8(setend be ) @ ensure we are in BE8 mode
> #ifdef CONFIG_ARM_VIRT_EXT
> bl __hyp_stub_install
> #endif
> @@ -170,7 +171,7 @@ ENTRY(stext)
> add r12, r12, r10
> ret r12
> 1: b __enable_mmu
> -ENDPROC(stext)
> +ENDPROC(primary_startup)
> .ltorg
>
> /*
> @@ -512,7 +513,7 @@ ENDPROC(__turn_mmu_on)
>
>
> #ifdef CONFIG_SMP_ON_UP
> - __HEAD
> + __INIT
> __fixup_smp:
> and r3, r9, #0x000f0000 @ architecture version
> teq r3, #0x000f0000 @ CPU ID supported?
> diff --git a/arch/arm/kernel/phys2virt.S b/arch/arm/kernel/phys2virt.S
> index fb53db78fe7850ba..96e76715d4f6e9f1 100644
> --- a/arch/arm/kernel/phys2virt.S
> +++ b/arch/arm/kernel/phys2virt.S
> @@ -27,7 +27,7 @@
> * r1 = machine no, r2 = atags or dtb,
> * r8 = phys_offset, r9 = cpuid, r10 = procinfo
> */
> - __HEAD
> + __INIT
> ENTRY(__fixup_pv_table)
> mov r0, r8, lsr #PAGE_SHIFT @ convert to PFN
> str_l r0, __pv_phys_pfn_offset, r3
> diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
> index 76678732c60da42e..5cb37390e21238ec 100644
> --- a/arch/arm/kernel/vmlinux-xip.lds.S
> +++ b/arch/arm/kernel/vmlinux-xip.lds.S
> @@ -49,13 +49,10 @@ SECTIONS
> . = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
> _xiprom = .; /* XIP ROM area to be mapped */
>
> - .head.text : {
> - _text = .;
> - HEAD_TEXT
> - }
> -
> .text : { /* Real text segment */
> + _text = .;
> _stext = .; /* Text and read-only data */
> + HEAD_TEXT
> ARM_TEXT
> }
>
> diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
> index aa12b65a7fd6a8cc..af819e1256a4c8e2 100644
> --- a/arch/arm/kernel/vmlinux.lds.S
> +++ b/arch/arm/kernel/vmlinux.lds.S
> @@ -48,20 +48,10 @@ SECTIONS
> }
>
> . = KERNEL_OFFSET + TEXT_OFFSET;
> - .head.text : {
> - _text = .;
> - HEAD_TEXT
> - }
> -
> -#ifdef CONFIG_STRICT_KERNEL_RWX
> - . = ALIGN(1<<SECTION_SHIFT);
> -#endif
> -
> -#ifdef CONFIG_ARM_MPU
> - . = ALIGN(PMSAv8_MINALIGN);
> -#endif
> .text : { /* Real text segment */
> + _text = .;
> _stext = .; /* Text and read-only data */
> + HEAD_TEXT
> ARM_TEXT
> }
>
> --
> 2.39.2
>
More information about the linux-arm-kernel
mailing list