linker script: use separate simpler definition for PERCPU()
authorTejun Heo <tj@kernel.org>
Fri, 30 Jan 2009 07:32:22 +0000 (16:32 +0900)
committerIngo Molnar <mingo@elte.hu>
Fri, 30 Jan 2009 22:27:46 +0000 (23:27 +0100)
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: Tejun Heo <tj@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
include/asm-generic/vmlinux.lds.h

index 53e21f3..5406e70 100644 (file)
  * 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) = .;                             \
  * 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) = .;                      \
+       }