powerpc: Build kernel with -mcmodel=medium
authorAnton Blanchard <anton@samba.org>
Mon, 26 Nov 2012 17:41:08 +0000 (17:41 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Thu, 10 Jan 2013 06:00:31 +0000 (17:00 +1100)
Finally remove the two level TOC and build with -mcmodel=medium.

Unfortunately we can't build modules with -mcmodel=medium due to
the tricks the kernel module loader plays with percpu data:

# -mcmodel=medium breaks modules because it uses 32bit offsets from
# the TOC pointer to create pointers where possible. Pointers into the
# percpu data area are created by this method.
#
# The kernel module loader relocates the percpu data section from the
# original location (starting with 0xd...) to somewhere in the base
# kernel percpu data space (starting with 0xc...). We need a full
# 64bit relocation for this to work, hence -mcmodel=large.

On older kernels we fall back to the two level TOC (-mminimal-toc)

Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/Makefile
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/module_64.c
arch/powerpc/lib/Makefile
arch/powerpc/mm/Makefile
arch/powerpc/oprofile/Makefile
arch/powerpc/platforms/pseries/Makefile
arch/powerpc/platforms/wsp/Makefile
arch/powerpc/sysdev/Makefile
arch/powerpc/xmon/Makefile

index 78c2b02..31d8965 100644 (file)
@@ -67,7 +67,24 @@ LDFLAGS_vmlinux-y := -Bstatic
 LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
 LDFLAGS_vmlinux        := $(LDFLAGS_vmlinux-y)
 
-CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=no -mcall-aixdesc
+ifeq ($(CONFIG_PPC64),y)
+ifeq ($(call cc-option-yn,-mcmodel=medium),y)
+       # -mcmodel=medium breaks modules because it uses 32bit offsets from
+       # the TOC pointer to create pointers where possible. Pointers into the
+       # percpu data area are created by this method.
+       #
+       # The kernel module loader relocates the percpu data section from the
+       # original location (starting with 0xd...) to somewhere in the base
+       # kernel percpu data space (starting with 0xc...). We need a full
+       # 64bit relocation for this to work, hence -mcmodel=large.
+       KBUILD_CFLAGS_MODULE += -mcmodel=large
+else
+       export NO_MINIMAL_TOC := -mno-minimal-toc
+endif
+endif
+
+CFLAGS-$(CONFIG_PPC64) := -mtraceback=no -mcall-aixdesc
+CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcmodel=medium,-mminimal-toc)
 CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple
 
 CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4)
index 2f6ef4e..b4f0e36 100644 (file)
@@ -7,7 +7,7 @@ CFLAGS_ptrace.o         += -DUTS_MACHINE='"$(UTS_MACHINE)"'
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
 ifeq ($(CONFIG_PPC64),y)
-CFLAGS_prom_init.o     += -mno-minimal-toc
+CFLAGS_prom_init.o     += $(NO_MINIMAL_TOC)
 endif
 ifeq ($(CONFIG_PPC32),y)
 CFLAGS_prom_init.o      += -fPIC
index 116f086..1697a25 100644 (file)
@@ -169,6 +169,7 @@ _GLOBAL(generic_secondary_thread_init)
 
        /* get a valid TOC pointer, wherever we're mapped at */
        bl      .relative_toc
+       tovirt(r2,r2)
 
 #ifdef CONFIG_PPC_BOOK3E
        /* Book3E initialization */
@@ -195,6 +196,7 @@ _GLOBAL(generic_secondary_smp_init)
 
        /* get a valid TOC pointer, wherever we're mapped at */
        bl      .relative_toc
+       tovirt(r2,r2)
 
 #ifdef CONFIG_PPC_BOOK3E
        /* Book3E initialization */
@@ -531,6 +533,7 @@ _GLOBAL(pmac_secondary_start)
 
        /* get TOC pointer (real address) */
        bl      .relative_toc
+       tovirt(r2,r2)
 
        /* Copy some CPU settings from CPU 0 */
        bl      .__restore_cpu_ppc970
@@ -665,6 +668,13 @@ _GLOBAL(enable_64b_mode)
  * This puts the TOC pointer into r2, offset by 0x8000 (as expected
  * by the toolchain).  It computes the correct value for wherever we
  * are running at the moment, using position-independent code.
+ *
+ * Note: The compiler constructs pointers using offsets from the
+ * TOC in -mcmodel=medium mode. After we relocate to 0 but before
+ * the MMU is on we need our TOC to be a virtual address otherwise
+ * these pointers will be real addresses which may get stored and
+ * accessed later with the MMU on. We use tovirt() at the call
+ * sites to handle this.
  */
 _GLOBAL(relative_toc)
        mflr    r0
@@ -681,8 +691,9 @@ p_toc:      .llong  __toc_start + 0x8000 - 0b
  * This is where the main kernel code starts.
  */
 _INIT_STATIC(start_here_multiplatform)
-       /* set up the TOC (real address) */
-       bl      .relative_toc
+       /* set up the TOC */
+       bl      .relative_toc
+       tovirt(r2,r2)
 
        /* Clear out the BSS. It may have been done in prom_init,
         * already but that's irrelevant since prom_init will soon
index 9f44a77..6ee59a0 100644 (file)
@@ -386,6 +386,14 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                                | (value & 0xffff);
                        break;
 
+               case R_PPC64_TOC16_LO:
+                       /* Subtract TOC pointer */
+                       value -= my_r2(sechdrs, me);
+                       *((uint16_t *) location)
+                               = (*((uint16_t *) location) & ~0xffff)
+                               | (value & 0xffff);
+                       break;
+
                case R_PPC64_TOC16_DS:
                        /* Subtract TOC pointer */
                        value -= my_r2(sechdrs, me);
@@ -399,6 +407,28 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                                | (value & 0xfffc);
                        break;
 
+               case R_PPC64_TOC16_LO_DS:
+                       /* Subtract TOC pointer */
+                       value -= my_r2(sechdrs, me);
+                       if ((value & 3) != 0) {
+                               printk("%s: bad TOC16_LO_DS relocation (%lu)\n",
+                                      me->name, value);
+                               return -ENOEXEC;
+                       }
+                       *((uint16_t *) location)
+                               = (*((uint16_t *) location) & ~0xfffc)
+                               | (value & 0xfffc);
+                       break;
+
+               case R_PPC64_TOC16_HA:
+                       /* Subtract TOC pointer */
+                       value -= my_r2(sechdrs, me);
+                       value = ((value + 0x8000) >> 16);
+                       *((uint16_t *) location)
+                               = (*((uint16_t *) location) & ~0xffff)
+                               | (value & 0xffff);
+                       break;
+
                case R_PPC_REL24:
                        /* FIXME: Handle weak symbols here --RR */
                        if (sym->st_shndx == SHN_UNDEF) {
index 746e0c8..fa48a4c 100644 (file)
@@ -4,7 +4,7 @@
 
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ccflags-$(CONFIG_PPC64)        := -mno-minimal-toc
+ccflags-$(CONFIG_PPC64)        := $(NO_MINIMAL_TOC)
 
 CFLAGS_REMOVE_code-patching.o = -pg
 CFLAGS_REMOVE_feature-fixups.o = -pg
index 3787b61..cf16b57 100644 (file)
@@ -4,7 +4,7 @@
 
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ccflags-$(CONFIG_PPC64)        := -mno-minimal-toc
+ccflags-$(CONFIG_PPC64)        := $(NO_MINIMAL_TOC)
 
 obj-y                          := fault.o mem.o pgtable.o gup.o \
                                   init_$(CONFIG_WORD_SIZE).o \
index 73456c4..751ec7b 100644 (file)
@@ -1,6 +1,6 @@
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ccflags-$(CONFIG_PPC64)        := -mno-minimal-toc
+ccflags-$(CONFIG_PPC64)        := $(NO_MINIMAL_TOC)
 
 obj-$(CONFIG_OPROFILE) += oprofile.o
 
index 890622b..53866e5 100644 (file)
@@ -1,4 +1,4 @@
-ccflags-$(CONFIG_PPC64)                        := -mno-minimal-toc
+ccflags-$(CONFIG_PPC64)                        := $(NO_MINIMAL_TOC)
 ccflags-$(CONFIG_PPC_PSERIES_DEBUG)    += -DDEBUG
 
 obj-y                  := lpar.o hvCall.o nvram.o reconfig.o \
index 56817ac..162fc60 100644 (file)
@@ -1,4 +1,4 @@
-ccflags-y                      += -mno-minimal-toc
+ccflags-y                      += $(NO_MINIMAL_TOC)
 
 obj-y                          += setup.o ics.o wsp.o
 obj-$(CONFIG_PPC_PSR2)         += psr2.o
index f44f09f..eca3d19 100644 (file)
@@ -1,6 +1,6 @@
 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
-ccflags-$(CONFIG_PPC64)                := -mno-minimal-toc
+ccflags-$(CONFIG_PPC64)                := $(NO_MINIMAL_TOC)
 
 mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o
 obj-$(CONFIG_MPIC)             += mpic.o $(mpic-msi-obj-y)
index b49fdbd..1278788 100644 (file)
@@ -4,7 +4,7 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
 
 GCOV_PROFILE := n
 
-ccflags-$(CONFIG_PPC64) := -mno-minimal-toc
+ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
 
 obj-y                  += xmon.o nonstdio.o