linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] arm64: fix non-converging vmlinux link
@ 2021-09-27  9:30 Arnd Bergmann
  2021-09-27 10:48 ` Mark Rutland
  0 siblings, 1 reply; 2+ messages in thread
From: Arnd Bergmann @ 2021-09-27  9:30 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon
  Cc: Ard Biesheuvel, Arnd Bergmann, Mark Rutland, Marc Zyngier,
	David Brazdil, linux-arm-kernel, linux-kernel

From: Ard Biesheuvel <ardb@kernel.org>

When the size of the vmlinux file is just below 64MB, the kernel
may fail to link with lld, producing output such as

ld.lld: error: assignment to symbol init_pg_end does not converge
ld.lld: error: assignment to symbol __pecoff_data_size does not converge

Change the INIT_DIR_SIZE definition to include init_pg_dir
to get a stable size calculation.

Arnd did the original report and analysis, but Ard figured what
to do about and wrote the changes to the code.

Link: https://github.com/ClangBuiltLinux/linux/issues/1219
Co-developed-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
Ard, I had this in my randconfig tree with comment "Ard will
submit this with a proper changelog", but it seems we both forgot
about it, or maybe there was something wrong with it in the
end.

While looking for randconfig -Werror warnings in mainline I came
across it again and can confirm that this patch (or something like
it) is still needed. Let me know if you are happy with this version
or if you have a better description for it. I unfortunately forgot
the details of how this works.
---
 arch/arm64/include/asm/kernel-pgtable.h | 2 +-
 arch/arm64/kernel/head.S                | 5 ++---
 arch/arm64/kernel/vmlinux.lds.S         | 3 +++
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
index 96dc0f7da258..5c622c18280a 100644
--- a/arch/arm64/include/asm/kernel-pgtable.h
+++ b/arch/arm64/include/asm/kernel-pgtable.h
@@ -86,7 +86,7 @@
 			+ EARLY_PGDS((vstart), (vend)) 	/* each PGDIR needs a next level page table */	\
 			+ EARLY_PUDS((vstart), (vend))	/* each PUD needs a next level page table */	\
 			+ EARLY_PMDS((vstart), (vend)))	/* each PMD needs a next level page table */
-#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end))
+#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, init_pg_dir))
 #define IDMAP_DIR_SIZE		(IDMAP_PGTABLE_LEVELS * PAGE_SIZE)
 
 /* Initial memory map size */
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 17962452e31d..2c3011660e48 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -366,10 +366,9 @@ SYM_FUNC_START_LOCAL(__create_page_tables)
 	mov_q	x5, KIMAGE_VADDR		// compile time __va(_text)
 	add	x5, x5, x23			// add KASLR displacement
 	mov	x4, PTRS_PER_PGD
-	adrp	x6, _end			// runtime __pa(_end)
 	adrp	x3, _text			// runtime __pa(_text)
-	sub	x6, x6, x3			// _end - _text
-	add	x6, x6, x5			// runtime __va(_end)
+	sub	x6, x0, x3			// init_pg_dir - _text
+	add	x6, x6, x5			// runtime __va(init_pg_dir)
 
 	map_memory x0, x1, x5, x6, x7, x3, x4, x10, x11, x12, x13, x14
 
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index f6b1a88245db..4792ddd1ae73 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -287,6 +287,9 @@ SECTIONS
 	BSS_SECTION(SBSS_ALIGN, 0, 0)
 
 	. = ALIGN(PAGE_SIZE);
+
+	/* ----- kernel virtual mapping ends here ---- */
+
 	init_pg_dir = .;
 	. += INIT_DIR_SIZE;
 	init_pg_end = .;
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] arm64: fix non-converging vmlinux link
  2021-09-27  9:30 [PATCH] arm64: fix non-converging vmlinux link Arnd Bergmann
@ 2021-09-27 10:48 ` Mark Rutland
  0 siblings, 0 replies; 2+ messages in thread
From: Mark Rutland @ 2021-09-27 10:48 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Catalin Marinas, Will Deacon, Ard Biesheuvel, Arnd Bergmann,
	Marc Zyngier, David Brazdil, linux-arm-kernel, linux-kernel

Hi Arnd, Ard,

On Mon, Sep 27, 2021 at 11:30:11AM +0200, Arnd Bergmann wrote:
> From: Ard Biesheuvel <ardb@kernel.org>
> 
> When the size of the vmlinux file is just below 64MB, the kernel
> may fail to link with lld, producing output such as
> 
> ld.lld: error: assignment to symbol init_pg_end does not converge
> ld.lld: error: assignment to symbol __pecoff_data_size does not converge
> 
> Change the INIT_DIR_SIZE definition to include init_pg_dir
                                        ^
Missing "not" here ---------------------'

We *need* to access `init_pg_dir` while using `init_pg_dir`, since e.g.
early_fixmap_init() needs to conntect the fixmap tables into it, so we
*must* map at least a portion of `init_pg_dir`.

We happen to over-map when using 4K pages, and so depending on the
alignment and size of the kernel Image this can work by chance. Also,
prior to v5.15-rc1, we'd over-map in all configurations, and this could
happen to work, but that was fixed in commit:

  90268574a3e8a6b8 ("arm64: head: avoid over-mapping in map_memory")

So as-is, this patch regresses working configurations at runtime,
including all 16K and 64K configs.

Is there some way we can over-estimate the size such that this will
converge? e.g. add some alignment padding such that `_end` won't
oscillate as `init_pg_end` changes?

Thanks,
Mark.

> to get a stable size calculation.
> 
> Arnd did the original report and analysis, but Ard figured what
> to do about and wrote the changes to the code.
> 
> Link: https://github.com/ClangBuiltLinux/linux/issues/1219
> Co-developed-by: Ard Biesheuvel <ardb@kernel.org>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> Ard, I had this in my randconfig tree with comment "Ard will
> submit this with a proper changelog", but it seems we both forgot
> about it, or maybe there was something wrong with it in the
> end.
> 
> While looking for randconfig -Werror warnings in mainline I came
> across it again and can confirm that this patch (or something like
> it) is still needed. Let me know if you are happy with this version
> or if you have a better description for it. I unfortunately forgot
> the details of how this works.
> ---
>  arch/arm64/include/asm/kernel-pgtable.h | 2 +-
>  arch/arm64/kernel/head.S                | 5 ++---
>  arch/arm64/kernel/vmlinux.lds.S         | 3 +++
>  3 files changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
> index 96dc0f7da258..5c622c18280a 100644
> --- a/arch/arm64/include/asm/kernel-pgtable.h
> +++ b/arch/arm64/include/asm/kernel-pgtable.h
> @@ -86,7 +86,7 @@
>  			+ EARLY_PGDS((vstart), (vend)) 	/* each PGDIR needs a next level page table */	\
>  			+ EARLY_PUDS((vstart), (vend))	/* each PUD needs a next level page table */	\
>  			+ EARLY_PMDS((vstart), (vend)))	/* each PMD needs a next level page table */
> -#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end))
> +#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, init_pg_dir))
>  #define IDMAP_DIR_SIZE		(IDMAP_PGTABLE_LEVELS * PAGE_SIZE)
>  
>  /* Initial memory map size */
> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index 17962452e31d..2c3011660e48 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -366,10 +366,9 @@ SYM_FUNC_START_LOCAL(__create_page_tables)
>  	mov_q	x5, KIMAGE_VADDR		// compile time __va(_text)
>  	add	x5, x5, x23			// add KASLR displacement
>  	mov	x4, PTRS_PER_PGD
> -	adrp	x6, _end			// runtime __pa(_end)
>  	adrp	x3, _text			// runtime __pa(_text)
> -	sub	x6, x6, x3			// _end - _text
> -	add	x6, x6, x5			// runtime __va(_end)
> +	sub	x6, x0, x3			// init_pg_dir - _text
> +	add	x6, x6, x5			// runtime __va(init_pg_dir)
>  
>  	map_memory x0, x1, x5, x6, x7, x3, x4, x10, x11, x12, x13, x14
>  
> diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> index f6b1a88245db..4792ddd1ae73 100644
> --- a/arch/arm64/kernel/vmlinux.lds.S
> +++ b/arch/arm64/kernel/vmlinux.lds.S
> @@ -287,6 +287,9 @@ SECTIONS
>  	BSS_SECTION(SBSS_ALIGN, 0, 0)
>  
>  	. = ALIGN(PAGE_SIZE);
> +
> +	/* ----- kernel virtual mapping ends here ---- */
> +
>  	init_pg_dir = .;
>  	. += INIT_DIR_SIZE;
>  	init_pg_end = .;
> -- 
> 2.29.2
> 

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-09-27 10:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-27  9:30 [PATCH] arm64: fix non-converging vmlinux link Arnd Bergmann
2021-09-27 10:48 ` Mark Rutland

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).