Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ac6cffe authored by Tejun Heo's avatar Tejun Heo Committed by Ingo Molnar
Browse files

linker script: use separate simpler definition for PERCPU()



Impact: fix linker screwup on x86_32

Recent x86_64 zerobased patches introduced PERCPU_VADDR() to put
.data.percpu to a predefined address and re-defined PERCPU() in terms
of it.  The new macro defined one extra symbol, __per_cpu_load, for
LMA of the section so that the init data could be accessed.  This new
symbol introduced the following problems to x86_32.

1. If __per_cpu_load is defined outside of .data.percpu as an absolute
   symbol, relocation generation for relocatable kernel fails due to
   absolute relocation.

2. If __per_cpu_load is put inside .data.percpu with absolute address
   assignment to work around #1, linker gets confused and under
   certain configurations ends up relocating the symbol against
   .data.percpu such that the load address gets added on top of
   already set load address.

As x86_32 doesn't use predefined address for .data.percpu, there's no
need for it to care about the possibility of __per_cpu_load being
different from __per_cpu_start.

This patch defines PERCPU() separately so that __per_cpu_load is
defined inside .data.percpu so that everything is ordinary
linking-wise.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent c43e0e46
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -445,10 +445,9 @@
 * section in the linker script will go there too.  @phdr should have
 * a leading colon.
 *
 * This macro defines three symbols, __per_cpu_load, __per_cpu_start
 * and __per_cpu_end.  The first one is the vaddr of loaded percpu
 * init data.  __per_cpu_start equals @vaddr and __per_cpu_end is the
 * end offset.
 * Note that this macros defines __per_cpu_load as an absolute symbol.
 * If there is no need to put the percpu section at a predetermined
 * address, use PERCPU().
 */
#define PERCPU_VADDR(vaddr, phdr)					\
	VMLINUX_SYMBOL(__per_cpu_load) = .;				\
@@ -470,7 +469,20 @@
 * Align to @align and outputs output section for percpu area.  This
 * macro doesn't maniuplate @vaddr or @phdr and __per_cpu_load and
 * __per_cpu_start will be identical.
 *
 * This macro is equivalent to ALIGN(align); PERCPU_VADDR( , ) except
 * that __per_cpu_load is defined as a relative symbol against
 * .data.percpu which is required for relocatable x86_32
 * configuration.
 */
#define PERCPU(align)							\
	. = ALIGN(align);						\
	PERCPU_VADDR( , )
	.data.percpu	: AT(ADDR(.data.percpu) - LOAD_OFFSET) {	\
		VMLINUX_SYMBOL(__per_cpu_load) = .;			\
		VMLINUX_SYMBOL(__per_cpu_start) = .;			\
		*(.data.percpu.first)					\
		*(.data.percpu.page_aligned)				\
		*(.data.percpu)						\
		*(.data.percpu.shared_aligned)				\
		VMLINUX_SYMBOL(__per_cpu_end) = .;			\
	}