[PATCH] ARM: head: Remove 1-2 MiB of pointless padding

Ard Biesheuvel ardb at kernel.org
Mon May 8 07:55:26 PDT 2023


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>
---
 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