Skip to content

Commit dc0a083

Browse files
ardbiesheuvelwilldeacon
authored andcommitted
arm64: Work around convergence issue with LLD linker
LLD will occasionally error out with a '__init_end does not converge' error if INIT_IDMAP_DIR_SIZE is defined in terms of _end, as this results in a circular dependency. Counter this by dimensioning the initial IDMAP page tables based on a new boundary marker 'kimage_limit', and define it such that its value should not change as a result of the initdata segment being pushed over a 64k segment boundary due to changes in INIT_IDMAP_DIR_SIZE, provided that its value doesn't change by more than 2M between linker passes. Reported-by: Arnd Bergmann <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent e21560b commit dc0a083

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

arch/arm64/include/asm/kernel-pgtable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
#define INIT_DIR_SIZE (PAGE_SIZE * (EARLY_PAGES(SWAPPER_PGTABLE_LEVELS, KIMAGE_VADDR, _end, EXTRA_PAGE) \
5959
+ EARLY_SEGMENT_EXTRA_PAGES))
6060

61-
#define INIT_IDMAP_DIR_PAGES (EARLY_PAGES(INIT_IDMAP_PGTABLE_LEVELS, KIMAGE_VADDR, _end, 1))
61+
#define INIT_IDMAP_DIR_PAGES (EARLY_PAGES(INIT_IDMAP_PGTABLE_LEVELS, KIMAGE_VADDR, kimage_limit, 1))
6262
#define INIT_IDMAP_DIR_SIZE ((INIT_IDMAP_DIR_PAGES + EARLY_IDMAP_EXTRA_PAGES) * PAGE_SIZE)
6363

6464
#define INIT_IDMAP_FDT_PAGES (EARLY_PAGES(INIT_IDMAP_PGTABLE_LEVELS, 0UL, UL(MAX_FDT_SIZE), 1) - 1)

arch/arm64/kernel/image-vars.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,17 @@ KVM_NVHE_ALIAS(kvm_protected_mode_initialized);
146146
_kernel_codesize = ABSOLUTE(__inittext_end - _text);
147147
#endif
148148

149+
/*
150+
* LLD will occasionally error out with a '__init_end does not converge' error
151+
* if INIT_IDMAP_DIR_SIZE is defined in terms of _end, as this results in a
152+
* circular dependency. Counter this by dimensioning the initial IDMAP page
153+
* tables based on kimage_limit, which is defined such that its value should
154+
* not change as a result of the initdata segment being pushed over a 64k
155+
* segment boundary due to changes in INIT_IDMAP_DIR_SIZE, provided that its
156+
* value doesn't change by more than 2M between linker passes.
157+
*/
158+
kimage_limit = ALIGN(ABSOLUTE(_end + SZ_64K), SZ_2M);
159+
149160
#undef ASSERT
150161

151162
#endif /* __ARM64_KERNEL_IMAGE_VARS_H */

0 commit comments

Comments
 (0)