Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: assembler: define a Kconfig symbol for group relocation support

Nathan reports the group relocations go out of range in pathological
cases such as allyesconfig kernels, which have little chance of actually
booting but are still used in validation.

So add a Kconfig symbol for this feature, and make it depend on
!COMPILE_TEST.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

+28 -12
+12 -1
arch/arm/Kconfig
··· 128 128 select RTC_LIB 129 129 select SYS_SUPPORTS_APM_EMULATION 130 130 select THREAD_INFO_IN_TASK 131 - select HAVE_ARCH_VMAP_STACK if MMU && (!LD_IS_LLD || LLD_VERSION >= 140000) 131 + select HAVE_ARCH_VMAP_STACK if MMU && ARM_HAS_GROUP_RELOCS 132 132 select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M 133 133 # Above selects are sorted alphabetically; please add new ones 134 134 # according to that. Thanks. ··· 139 139 manufactured, but legacy ARM-based PC hardware remains popular in 140 140 Europe. There is an ARM Linux project with a web page at 141 141 <http://www.arm.linux.org.uk/>. 142 + 143 + config ARM_HAS_GROUP_RELOCS 144 + def_bool y 145 + depends on !LD_IS_LLD || LLD_VERSION >= 140000 146 + depends on !COMPILE_TEST 147 + help 148 + Whether or not to use R_ARM_ALU_PC_Gn or R_ARM_LDR_PC_Gn group 149 + relocations, which have been around for a long time, but were not 150 + supported in LLD until version 14. The combined range is -/+ 256 MiB, 151 + which is usually sufficient, but not for allyesconfig, so we disable 152 + this feature when doing compile testing. 142 153 143 154 config ARM_HAS_SG_CHAIN 144 155 bool
+4 -4
arch/arm/include/asm/assembler.h
··· 656 656 657 657 .macro __ldst_va, op, reg, tmp, sym, cond 658 658 #if __LINUX_ARM_ARCH__ >= 7 || \ 659 - (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) || \ 660 - (defined(CONFIG_LD_IS_LLD) && CONFIG_LLD_VERSION < 140000) 659 + !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \ 660 + (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) 661 661 mov_l \tmp, \sym, \cond 662 662 \op\cond \reg, [\tmp] 663 663 #else ··· 716 716 */ 717 717 .macro ldr_this_cpu, rd:req, sym:req, t1:req, t2:req 718 718 #if __LINUX_ARM_ARCH__ >= 7 || \ 719 - (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) || \ 720 - (defined(CONFIG_LD_IS_LLD) && CONFIG_LLD_VERSION < 140000) 719 + !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \ 720 + (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) 721 721 this_cpu_offset \t1 722 722 mov_l \t2, \sym 723 723 ldr \rd, [\t1, \t2]
+4 -4
arch/arm/include/asm/current.h
··· 37 37 #ifdef CONFIG_CPU_V6 38 38 "1: \n\t" 39 39 " .subsection 1 \n\t" 40 - #if !(defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) && \ 41 - !(defined(CONFIG_LD_IS_LLD) && CONFIG_LLD_VERSION < 140000) 40 + #if defined(CONFIG_ARM_HAS_GROUP_RELOCS) && \ 41 + !(defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) 42 42 "2: " LOAD_SYM_ARMV6(%0, __current) " \n\t" 43 43 " b 1b \n\t" 44 44 #else ··· 55 55 #endif 56 56 : "=r"(cur)); 57 57 #elif __LINUX_ARM_ARCH__>= 7 || \ 58 - (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) || \ 59 - (defined(CONFIG_LD_IS_LLD) && CONFIG_LLD_VERSION < 140000) 58 + !defined(CONFIG_ARM_HAS_GROUP_RELOCS) || \ 59 + (defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) 60 60 cur = __current; 61 61 #else 62 62 asm(LOAD_SYM_ARMV6(%0, __current) : "=r"(cur));
+2 -2
arch/arm/include/asm/percpu.h
··· 38 38 #ifdef CONFIG_CPU_V6 39 39 "1: \n\t" 40 40 " .subsection 1 \n\t" 41 - #if !(defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) && \ 42 - !(defined(CONFIG_LD_IS_LLD) && CONFIG_LLD_VERSION < 140000) 41 + #if defined(CONFIG_ARM_HAS_GROUP_RELOCS) && \ 42 + !(defined(MODULE) && defined(CONFIG_ARM_MODULE_PLTS)) 43 43 "2: " LOAD_SYM_ARMV6(%0, __per_cpu_offset) " \n\t" 44 44 " b 1b \n\t" 45 45 #else
+6 -1
arch/arm/kernel/module.c
··· 68 68 strstarts(name, ".ARM.exidx.exit"); 69 69 } 70 70 71 + #ifdef CONFIG_ARM_HAS_GROUP_RELOCS 71 72 /* 72 73 * This implements the partitioning algorithm for group relocations as 73 74 * documented in the ARM AArch32 ELF psABI (IHI 0044). ··· 104 103 } while (group--); 105 104 return shift; 106 105 } 106 + #endif 107 107 108 108 int 109 109 apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex, ··· 120 118 unsigned long loc; 121 119 Elf32_Sym *sym; 122 120 const char *symname; 121 + #ifdef CONFIG_ARM_HAS_GROUP_RELOCS 123 122 u32 shift, group = 1; 123 + #endif 124 124 s32 offset; 125 125 u32 tmp; 126 126 #ifdef CONFIG_THUMB2_KERNEL ··· 253 249 *(u32 *)loc = __opcode_to_mem_arm(tmp); 254 250 break; 255 251 252 + #ifdef CONFIG_ARM_HAS_GROUP_RELOCS 256 253 case R_ARM_ALU_PC_G0_NC: 257 254 group = 0; 258 255 fallthrough; ··· 301 296 } 302 297 *(u32 *)loc = __opcode_to_mem_arm((tmp & ~0xfff) | offset); 303 298 break; 304 - 299 + #endif 305 300 #ifdef CONFIG_THUMB2_KERNEL 306 301 case R_ARM_THM_CALL: 307 302 case R_ARM_THM_JUMP24: