[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