Commit 1fbe9cf2 authored by Anton Blanchard's avatar Anton Blanchard Committed by Benjamin Herrenschmidt

powerpc: Build kernel with -mcmodel=medium

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: default avatarAnton Blanchard <anton@samba.org>
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 5827d416
...@@ -67,7 +67,24 @@ LDFLAGS_vmlinux-y := -Bstatic ...@@ -67,7 +67,24 @@ LDFLAGS_vmlinux-y := -Bstatic
LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie
LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y) 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_PPC32) := -ffixed-r2 -mmultiple
CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4) CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4)
......
...@@ -7,7 +7,7 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' ...@@ -7,7 +7,7 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
ifeq ($(CONFIG_PPC64),y) ifeq ($(CONFIG_PPC64),y)
CFLAGS_prom_init.o += -mno-minimal-toc CFLAGS_prom_init.o += $(NO_MINIMAL_TOC)
endif endif
ifeq ($(CONFIG_PPC32),y) ifeq ($(CONFIG_PPC32),y)
CFLAGS_prom_init.o += -fPIC CFLAGS_prom_init.o += -fPIC
......
...@@ -169,6 +169,7 @@ _GLOBAL(generic_secondary_thread_init) ...@@ -169,6 +169,7 @@ _GLOBAL(generic_secondary_thread_init)
/* get a valid TOC pointer, wherever we're mapped at */ /* get a valid TOC pointer, wherever we're mapped at */
bl .relative_toc bl .relative_toc
tovirt(r2,r2)
#ifdef CONFIG_PPC_BOOK3E #ifdef CONFIG_PPC_BOOK3E
/* Book3E initialization */ /* Book3E initialization */
...@@ -195,6 +196,7 @@ _GLOBAL(generic_secondary_smp_init) ...@@ -195,6 +196,7 @@ _GLOBAL(generic_secondary_smp_init)
/* get a valid TOC pointer, wherever we're mapped at */ /* get a valid TOC pointer, wherever we're mapped at */
bl .relative_toc bl .relative_toc
tovirt(r2,r2)
#ifdef CONFIG_PPC_BOOK3E #ifdef CONFIG_PPC_BOOK3E
/* Book3E initialization */ /* Book3E initialization */
...@@ -531,6 +533,7 @@ _GLOBAL(pmac_secondary_start) ...@@ -531,6 +533,7 @@ _GLOBAL(pmac_secondary_start)
/* get TOC pointer (real address) */ /* get TOC pointer (real address) */
bl .relative_toc bl .relative_toc
tovirt(r2,r2)
/* Copy some CPU settings from CPU 0 */ /* Copy some CPU settings from CPU 0 */
bl .__restore_cpu_ppc970 bl .__restore_cpu_ppc970
...@@ -665,6 +668,13 @@ _GLOBAL(enable_64b_mode) ...@@ -665,6 +668,13 @@ _GLOBAL(enable_64b_mode)
* This puts the TOC pointer into r2, offset by 0x8000 (as expected * This puts the TOC pointer into r2, offset by 0x8000 (as expected
* by the toolchain). It computes the correct value for wherever we * by the toolchain). It computes the correct value for wherever we
* are running at the moment, using position-independent code. * 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) _GLOBAL(relative_toc)
mflr r0 mflr r0
...@@ -681,8 +691,9 @@ p_toc: .llong __toc_start + 0x8000 - 0b ...@@ -681,8 +691,9 @@ p_toc: .llong __toc_start + 0x8000 - 0b
* This is where the main kernel code starts. * This is where the main kernel code starts.
*/ */
_INIT_STATIC(start_here_multiplatform) _INIT_STATIC(start_here_multiplatform)
/* set up the TOC (real address) */ /* set up the TOC */
bl .relative_toc bl .relative_toc
tovirt(r2,r2)
/* Clear out the BSS. It may have been done in prom_init, /* Clear out the BSS. It may have been done in prom_init,
* already but that's irrelevant since prom_init will soon * already but that's irrelevant since prom_init will soon
......
...@@ -386,6 +386,14 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, ...@@ -386,6 +386,14 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
| (value & 0xffff); | (value & 0xffff);
break; 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: case R_PPC64_TOC16_DS:
/* Subtract TOC pointer */ /* Subtract TOC pointer */
value -= my_r2(sechdrs, me); value -= my_r2(sechdrs, me);
...@@ -399,6 +407,28 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, ...@@ -399,6 +407,28 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
| (value & 0xfffc); | (value & 0xfffc);
break; 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: case R_PPC_REL24:
/* FIXME: Handle weak symbols here --RR */ /* FIXME: Handle weak symbols here --RR */
if (sym->st_shndx == SHN_UNDEF) { if (sym->st_shndx == SHN_UNDEF) {
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror 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_code-patching.o = -pg
CFLAGS_REMOVE_feature-fixups.o = -pg CFLAGS_REMOVE_feature-fixups.o = -pg
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror 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 \ obj-y := fault.o mem.o pgtable.o gup.o \
init_$(CONFIG_WORD_SIZE).o \ init_$(CONFIG_WORD_SIZE).o \
......
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
ccflags-$(CONFIG_PPC64) := -mno-minimal-toc ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
obj-$(CONFIG_OPROFILE) += oprofile.o obj-$(CONFIG_OPROFILE) += oprofile.o
......
ccflags-$(CONFIG_PPC64) := -mno-minimal-toc ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG
obj-y := lpar.o hvCall.o nvram.o reconfig.o \ obj-y := lpar.o hvCall.o nvram.o reconfig.o \
......
ccflags-y += -mno-minimal-toc ccflags-y += $(NO_MINIMAL_TOC)
obj-y += setup.o ics.o wsp.o obj-y += setup.o ics.o wsp.o
obj-$(CONFIG_PPC_PSR2) += psr2.o obj-$(CONFIG_PPC_PSR2) += psr2.o
......
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror 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 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) obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
......
...@@ -4,7 +4,7 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror ...@@ -4,7 +4,7 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
GCOV_PROFILE := n GCOV_PROFILE := n
ccflags-$(CONFIG_PPC64) := -mno-minimal-toc ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC)
obj-y += xmon.o nonstdio.o obj-y += xmon.o nonstdio.o
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment