diff options
author | Anton Blanchard <anton@samba.org> | 2012-11-26 12:41:08 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-01-10 01:00:31 -0500 |
commit | 1fbe9cf2598dae3bd464d860bd89c67b1ff8682b (patch) | |
tree | c07f1fe789777669466bc3077a5f0afa70cf83b6 /arch/powerpc | |
parent | 5827d4165ac608d7c26fa68701391e80824ee5c9 (diff) |
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>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/Makefile | 19 | ||||
-rw-r--r-- | arch/powerpc/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 15 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_64.c | 30 | ||||
-rw-r--r-- | arch/powerpc/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/mm/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/oprofile/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/wsp/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/sysdev/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/xmon/Makefile | 2 |
11 files changed, 69 insertions, 11 deletions
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 78c2b024371a..31d8965e0847 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -67,7 +67,24 @@ LDFLAGS_vmlinux-y := -Bstatic | |||
67 | LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie | 67 | LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) := -pie |
68 | LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y) | 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 | CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple | 88 | CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple |
72 | 89 | ||
73 | CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4) | 90 | CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4) |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 2f6ef4ed5abf..b4f0e360e414 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -7,7 +7,7 @@ CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' | |||
7 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 7 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror |
8 | 8 | ||
9 | ifeq ($(CONFIG_PPC64),y) | 9 | ifeq ($(CONFIG_PPC64),y) |
10 | CFLAGS_prom_init.o += -mno-minimal-toc | 10 | CFLAGS_prom_init.o += $(NO_MINIMAL_TOC) |
11 | endif | 11 | endif |
12 | ifeq ($(CONFIG_PPC32),y) | 12 | ifeq ($(CONFIG_PPC32),y) |
13 | CFLAGS_prom_init.o += -fPIC | 13 | CFLAGS_prom_init.o += -fPIC |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 116f0868695b..1697a25ebe91 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -169,6 +169,7 @@ _GLOBAL(generic_secondary_thread_init) | |||
169 | 169 | ||
170 | /* get a valid TOC pointer, wherever we're mapped at */ | 170 | /* get a valid TOC pointer, wherever we're mapped at */ |
171 | bl .relative_toc | 171 | bl .relative_toc |
172 | tovirt(r2,r2) | ||
172 | 173 | ||
173 | #ifdef CONFIG_PPC_BOOK3E | 174 | #ifdef CONFIG_PPC_BOOK3E |
174 | /* Book3E initialization */ | 175 | /* Book3E initialization */ |
@@ -195,6 +196,7 @@ _GLOBAL(generic_secondary_smp_init) | |||
195 | 196 | ||
196 | /* get a valid TOC pointer, wherever we're mapped at */ | 197 | /* get a valid TOC pointer, wherever we're mapped at */ |
197 | bl .relative_toc | 198 | bl .relative_toc |
199 | tovirt(r2,r2) | ||
198 | 200 | ||
199 | #ifdef CONFIG_PPC_BOOK3E | 201 | #ifdef CONFIG_PPC_BOOK3E |
200 | /* Book3E initialization */ | 202 | /* Book3E initialization */ |
@@ -531,6 +533,7 @@ _GLOBAL(pmac_secondary_start) | |||
531 | 533 | ||
532 | /* get TOC pointer (real address) */ | 534 | /* get TOC pointer (real address) */ |
533 | bl .relative_toc | 535 | bl .relative_toc |
536 | tovirt(r2,r2) | ||
534 | 537 | ||
535 | /* Copy some CPU settings from CPU 0 */ | 538 | /* Copy some CPU settings from CPU 0 */ |
536 | bl .__restore_cpu_ppc970 | 539 | bl .__restore_cpu_ppc970 |
@@ -665,6 +668,13 @@ _GLOBAL(enable_64b_mode) | |||
665 | * This puts the TOC pointer into r2, offset by 0x8000 (as expected | 668 | * This puts the TOC pointer into r2, offset by 0x8000 (as expected |
666 | * by the toolchain). It computes the correct value for wherever we | 669 | * by the toolchain). It computes the correct value for wherever we |
667 | * are running at the moment, using position-independent code. | 670 | * are running at the moment, using position-independent code. |
671 | * | ||
672 | * Note: The compiler constructs pointers using offsets from the | ||
673 | * TOC in -mcmodel=medium mode. After we relocate to 0 but before | ||
674 | * the MMU is on we need our TOC to be a virtual address otherwise | ||
675 | * these pointers will be real addresses which may get stored and | ||
676 | * accessed later with the MMU on. We use tovirt() at the call | ||
677 | * sites to handle this. | ||
668 | */ | 678 | */ |
669 | _GLOBAL(relative_toc) | 679 | _GLOBAL(relative_toc) |
670 | mflr r0 | 680 | mflr r0 |
@@ -681,8 +691,9 @@ p_toc: .llong __toc_start + 0x8000 - 0b | |||
681 | * This is where the main kernel code starts. | 691 | * This is where the main kernel code starts. |
682 | */ | 692 | */ |
683 | _INIT_STATIC(start_here_multiplatform) | 693 | _INIT_STATIC(start_here_multiplatform) |
684 | /* set up the TOC (real address) */ | 694 | /* set up the TOC */ |
685 | bl .relative_toc | 695 | bl .relative_toc |
696 | tovirt(r2,r2) | ||
686 | 697 | ||
687 | /* Clear out the BSS. It may have been done in prom_init, | 698 | /* Clear out the BSS. It may have been done in prom_init, |
688 | * already but that's irrelevant since prom_init will soon | 699 | * already but that's irrelevant since prom_init will soon |
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 9f44a775a106..6ee59a0eb268 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c | |||
@@ -386,6 +386,14 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
386 | | (value & 0xffff); | 386 | | (value & 0xffff); |
387 | break; | 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 | case R_PPC64_TOC16_DS: | 397 | case R_PPC64_TOC16_DS: |
390 | /* Subtract TOC pointer */ | 398 | /* Subtract TOC pointer */ |
391 | value -= my_r2(sechdrs, me); | 399 | value -= my_r2(sechdrs, me); |
@@ -399,6 +407,28 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
399 | | (value & 0xfffc); | 407 | | (value & 0xfffc); |
400 | break; | 408 | break; |
401 | 409 | ||
410 | case R_PPC64_TOC16_LO_DS: | ||
411 | /* Subtract TOC pointer */ | ||
412 | value -= my_r2(sechdrs, me); | ||
413 | if ((value & 3) != 0) { | ||
414 | printk("%s: bad TOC16_LO_DS relocation (%lu)\n", | ||
415 | me->name, value); | ||
416 | return -ENOEXEC; | ||
417 | } | ||
418 | *((uint16_t *) location) | ||
419 | = (*((uint16_t *) location) & ~0xfffc) | ||
420 | | (value & 0xfffc); | ||
421 | break; | ||
422 | |||
423 | case R_PPC64_TOC16_HA: | ||
424 | /* Subtract TOC pointer */ | ||
425 | value -= my_r2(sechdrs, me); | ||
426 | value = ((value + 0x8000) >> 16); | ||
427 | *((uint16_t *) location) | ||
428 | = (*((uint16_t *) location) & ~0xffff) | ||
429 | | (value & 0xffff); | ||
430 | break; | ||
431 | |||
402 | case R_PPC_REL24: | 432 | case R_PPC_REL24: |
403 | /* FIXME: Handle weak symbols here --RR */ | 433 | /* FIXME: Handle weak symbols here --RR */ |
404 | if (sym->st_shndx == SHN_UNDEF) { | 434 | if (sym->st_shndx == SHN_UNDEF) { |
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 746e0c895cd7..fa48a4cc19a3 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 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 | CFLAGS_REMOVE_code-patching.o = -pg | 9 | CFLAGS_REMOVE_code-patching.o = -pg |
10 | CFLAGS_REMOVE_feature-fixups.o = -pg | 10 | CFLAGS_REMOVE_feature-fixups.o = -pg |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 3787b61f7d20..cf16b5733eaa 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 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 | obj-y := fault.o mem.o pgtable.o gup.o \ | 9 | obj-y := fault.o mem.o pgtable.o gup.o \ |
10 | init_$(CONFIG_WORD_SIZE).o \ | 10 | init_$(CONFIG_WORD_SIZE).o \ |
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 73456c4cec28..751ec7bd5018 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 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 | obj-$(CONFIG_OPROFILE) += oprofile.o | 5 | obj-$(CONFIG_OPROFILE) += oprofile.o |
6 | 6 | ||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 890622b87c8f..53866e537a92 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc | 1 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) |
2 | ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG | 2 | ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG |
3 | 3 | ||
4 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | 4 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ |
diff --git a/arch/powerpc/platforms/wsp/Makefile b/arch/powerpc/platforms/wsp/Makefile index 56817ac98fc9..162fc60125a2 100644 --- a/arch/powerpc/platforms/wsp/Makefile +++ b/arch/powerpc/platforms/wsp/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | ccflags-y += -mno-minimal-toc | 1 | ccflags-y += $(NO_MINIMAL_TOC) |
2 | 2 | ||
3 | obj-y += setup.o ics.o wsp.o | 3 | obj-y += setup.o ics.o wsp.o |
4 | obj-$(CONFIG_PPC_PSR2) += psr2.o | 4 | obj-$(CONFIG_PPC_PSR2) += psr2.o |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index f44f09f3d527..eca3d19304c7 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 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 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o | 5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o |
6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) | 6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) |
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index b49fdbd15808..1278788d96e3 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile | |||
@@ -4,7 +4,7 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | |||
4 | 4 | ||
5 | GCOV_PROFILE := n | 5 | GCOV_PROFILE := n |
6 | 6 | ||
7 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc | 7 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) |
8 | 8 | ||
9 | obj-y += xmon.o nonstdio.o | 9 | obj-y += xmon.o nonstdio.o |
10 | 10 | ||