Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Anton Blanchard <anton@samba.org>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Anton Blanchard and committed by
Benjamin Herrenschmidt
1fbe9cf2 5827d416

+69 -11
+18 -1
arch/powerpc/Makefile
··· 67 67 LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie 68 68 LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y) 69 69 70 - CFLAGS-$(CONFIG_PPC64) := -mminimal-toc -mtraceback=no -mcall-aixdesc 70 + ifeq ($(CONFIG_PPC64),y) 71 + ifeq ($(call cc-option-yn,-mcmodel=medium),y) 72 + # -mcmodel=medium breaks modules because it uses 32bit offsets from 73 + # the TOC pointer to create pointers where possible. Pointers into the 74 + # percpu data area are created by this method. 75 + # 76 + # The kernel module loader relocates the percpu data section from the 77 + # original location (starting with 0xd...) to somewhere in the base 78 + # kernel percpu data space (starting with 0xc...). We need a full 79 + # 64bit relocation for this to work, hence -mcmodel=large. 80 + KBUILD_CFLAGS_MODULE += -mcmodel=large 81 + else 82 + export NO_MINIMAL_TOC := -mno-minimal-toc 83 + endif 84 + endif 85 + 86 + CFLAGS-$(CONFIG_PPC64) := -mtraceback=no -mcall-aixdesc 87 + CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcmodel=medium,-mminimal-toc) 71 88 CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple 72 89 73 90 CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4)
+1 -1
arch/powerpc/kernel/Makefile
··· 7 7 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror 8 8 9 9 ifeq ($(CONFIG_PPC64),y) 10 - CFLAGS_prom_init.o += -mno-minimal-toc 10 + CFLAGS_prom_init.o += $(NO_MINIMAL_TOC) 11 11 endif 12 12 ifeq ($(CONFIG_PPC32),y) 13 13 CFLAGS_prom_init.o += -fPIC
+13 -2
arch/powerpc/kernel/head_64.S
··· 169 169 170 170 /* get a valid TOC pointer, wherever we're mapped at */ 171 171 bl .relative_toc 172 + tovirt(r2,r2) 172 173 173 174 #ifdef CONFIG_PPC_BOOK3E 174 175 /* Book3E initialization */ ··· 196 195 197 196 /* get a valid TOC pointer, wherever we're mapped at */ 198 197 bl .relative_toc 198 + tovirt(r2,r2) 199 199 200 200 #ifdef CONFIG_PPC_BOOK3E 201 201 /* Book3E initialization */ ··· 533 531 534 532 /* get TOC pointer (real address) */ 535 533 bl .relative_toc 534 + tovirt(r2,r2) 536 535 537 536 /* Copy some CPU settings from CPU 0 */ 538 537 bl .__restore_cpu_ppc970 ··· 668 665 * This puts the TOC pointer into r2, offset by 0x8000 (as expected 669 666 * by the toolchain). It computes the correct value for wherever we 670 667 * are running at the moment, using position-independent code. 668 + * 669 + * Note: The compiler constructs pointers using offsets from the 670 + * TOC in -mcmodel=medium mode. After we relocate to 0 but before 671 + * the MMU is on we need our TOC to be a virtual address otherwise 672 + * these pointers will be real addresses which may get stored and 673 + * accessed later with the MMU on. We use tovirt() at the call 674 + * sites to handle this. 671 675 */ 672 676 _GLOBAL(relative_toc) 673 677 mflr r0 ··· 691 681 * This is where the main kernel code starts. 692 682 */ 693 683 _INIT_STATIC(start_here_multiplatform) 694 - /* set up the TOC (real address) */ 695 - bl .relative_toc 684 + /* set up the TOC */ 685 + bl .relative_toc 686 + tovirt(r2,r2) 696 687 697 688 /* Clear out the BSS. It may have been done in prom_init, 698 689 * already but that's irrelevant since prom_init will soon
+30
arch/powerpc/kernel/module_64.c
··· 386 386 | (value & 0xffff); 387 387 break; 388 388 389 + case R_PPC64_TOC16_LO: 390 + /* Subtract TOC pointer */ 391 + value -= my_r2(sechdrs, me); 392 + *((uint16_t *) location) 393 + = (*((uint16_t *) location) & ~0xffff) 394 + | (value & 0xffff); 395 + break; 396 + 389 397 case R_PPC64_TOC16_DS: 390 398 /* Subtract TOC pointer */ 391 399 value -= my_r2(sechdrs, me); ··· 405 397 *((uint16_t *) location) 406 398 = (*((uint16_t *) location) & ~0xfffc) 407 399 | (value & 0xfffc); 400 + break; 401 + 402 + case R_PPC64_TOC16_LO_DS: 403 + /* Subtract TOC pointer */ 404 + value -= my_r2(sechdrs, me); 405 + if ((value & 3) != 0) { 406 + printk("%s: bad TOC16_LO_DS relocation (%lu)\n", 407 + me->name, value); 408 + return -ENOEXEC; 409 + } 410 + *((uint16_t *) location) 411 + = (*((uint16_t *) location) & ~0xfffc) 412 + | (value & 0xfffc); 413 + break; 414 + 415 + case R_PPC64_TOC16_HA: 416 + /* Subtract TOC pointer */ 417 + value -= my_r2(sechdrs, me); 418 + value = ((value + 0x8000) >> 16); 419 + *((uint16_t *) location) 420 + = (*((uint16_t *) location) & ~0xffff) 421 + | (value & 0xffff); 408 422 break; 409 423 410 424 case R_PPC_REL24:
+1 -1
arch/powerpc/lib/Makefile
··· 4 4 5 5 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror 6 6 7 - ccflags-$(CONFIG_PPC64) := -mno-minimal-toc 7 + ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) 8 8 9 9 CFLAGS_REMOVE_code-patching.o = -pg 10 10 CFLAGS_REMOVE_feature-fixups.o = -pg
+1 -1
arch/powerpc/mm/Makefile
··· 4 4 5 5 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror 6 6 7 - ccflags-$(CONFIG_PPC64) := -mno-minimal-toc 7 + ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) 8 8 9 9 obj-y := fault.o mem.o pgtable.o gup.o \ 10 10 init_$(CONFIG_WORD_SIZE).o \
+1 -1
arch/powerpc/oprofile/Makefile
··· 1 1 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror 2 2 3 - ccflags-$(CONFIG_PPC64) := -mno-minimal-toc 3 + ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) 4 4 5 5 obj-$(CONFIG_OPROFILE) += oprofile.o 6 6
+1 -1
arch/powerpc/platforms/pseries/Makefile
··· 1 - ccflags-$(CONFIG_PPC64) := -mno-minimal-toc 1 + ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) 2 2 ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG 3 3 4 4 obj-y := lpar.o hvCall.o nvram.o reconfig.o \
+1 -1
arch/powerpc/platforms/wsp/Makefile
··· 1 - ccflags-y += -mno-minimal-toc 1 + ccflags-y += $(NO_MINIMAL_TOC) 2 2 3 3 obj-y += setup.o ics.o wsp.o 4 4 obj-$(CONFIG_PPC_PSR2) += psr2.o
+1 -1
arch/powerpc/sysdev/Makefile
··· 1 1 subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror 2 2 3 - ccflags-$(CONFIG_PPC64) := -mno-minimal-toc 3 + ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) 4 4 5 5 mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o 6 6 obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y)
+1 -1
arch/powerpc/xmon/Makefile
··· 4 4 5 5 GCOV_PROFILE := n 6 6 7 - ccflags-$(CONFIG_PPC64) := -mno-minimal-toc 7 + ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) 8 8 9 9 obj-y += xmon.o nonstdio.o 10 10