diff options
-rw-r--r-- | arch/powerpc/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/sections.h | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 70 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom_init_check.sh | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/vmlinux.lds.S | 5 |
6 files changed, 68 insertions, 15 deletions
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index ba45cad088c9..78c2b024371a 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -136,6 +136,7 @@ head-$(CONFIG_FSL_BOOKE) := arch/powerpc/kernel/head_fsl_booke.o | |||
136 | head-$(CONFIG_PPC64) += arch/powerpc/kernel/entry_64.o | 136 | head-$(CONFIG_PPC64) += arch/powerpc/kernel/entry_64.o |
137 | head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o | 137 | head-$(CONFIG_PPC_FPU) += arch/powerpc/kernel/fpu.o |
138 | head-$(CONFIG_ALTIVEC) += arch/powerpc/kernel/vector.o | 138 | head-$(CONFIG_ALTIVEC) += arch/powerpc/kernel/vector.o |
139 | head-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += arch/powerpc/kernel/prom_init.o | ||
139 | 140 | ||
140 | core-y += arch/powerpc/kernel/ \ | 141 | core-y += arch/powerpc/kernel/ \ |
141 | arch/powerpc/mm/ \ | 142 | arch/powerpc/mm/ \ |
diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h index a0f358d4a00c..4ee06fe15de4 100644 --- a/arch/powerpc/include/asm/sections.h +++ b/arch/powerpc/include/asm/sections.h | |||
@@ -10,6 +10,9 @@ | |||
10 | 10 | ||
11 | extern char __end_interrupts[]; | 11 | extern char __end_interrupts[]; |
12 | 12 | ||
13 | extern char __prom_init_toc_start[]; | ||
14 | extern char __prom_init_toc_end[]; | ||
15 | |||
13 | static inline int in_kernel_text(unsigned long addr) | 16 | static inline int in_kernel_text(unsigned long addr) |
14 | { | 17 | { |
15 | if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end) | 18 | if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end) |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 44fbbea7697a..2f6ef4ed5abf 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -91,7 +91,6 @@ obj-$(CONFIG_RELOCATABLE_PPC32) += reloc_32.o | |||
91 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o | 91 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o |
92 | obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o | 92 | obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o |
93 | obj-$(CONFIG_KGDB) += kgdb.o | 93 | obj-$(CONFIG_KGDB) += kgdb.o |
94 | obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init.o | ||
95 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | 94 | obj-$(CONFIG_MODULES) += ppc_ksyms.o |
96 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | 95 | obj-$(CONFIG_BOOTX_TEXT) += btext.o |
97 | obj-$(CONFIG_SMP) += smp.o | 96 | obj-$(CONFIG_SMP) += smp.o |
@@ -142,6 +141,7 @@ GCOV_PROFILE_kprobes.o := n | |||
142 | extra-$(CONFIG_PPC_FPU) += fpu.o | 141 | extra-$(CONFIG_PPC_FPU) += fpu.o |
143 | extra-$(CONFIG_ALTIVEC) += vector.o | 142 | extra-$(CONFIG_ALTIVEC) += vector.o |
144 | extra-$(CONFIG_PPC64) += entry_64.o | 143 | extra-$(CONFIG_PPC64) += entry_64.o |
144 | extra-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init.o | ||
145 | 145 | ||
146 | extra-y += systbl_chk.i | 146 | extra-y += systbl_chk.i |
147 | $(obj)/systbl.o: systbl_chk | 147 | $(obj)/systbl.o: systbl_chk |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 779f34049a56..c78ac5698b99 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -66,8 +66,8 @@ | |||
66 | * is running at whatever address it has been loaded at. | 66 | * is running at whatever address it has been loaded at. |
67 | * On ppc32 we compile with -mrelocatable, which means that references | 67 | * On ppc32 we compile with -mrelocatable, which means that references |
68 | * to extern and static variables get relocated automatically. | 68 | * to extern and static variables get relocated automatically. |
69 | * On ppc64 we have to relocate the references explicitly with | 69 | * ppc64 objects are always relocatable, we just need to relocate the |
70 | * RELOC. (Note that strings count as static variables.) | 70 | * TOC. |
71 | * | 71 | * |
72 | * Because OF may have mapped I/O devices into the area starting at | 72 | * Because OF may have mapped I/O devices into the area starting at |
73 | * KERNELBASE, particularly on CHRP machines, we can't safely call | 73 | * KERNELBASE, particularly on CHRP machines, we can't safely call |
@@ -79,13 +79,12 @@ | |||
79 | * On ppc64, 64 bit values are truncated to 32 bits (and | 79 | * On ppc64, 64 bit values are truncated to 32 bits (and |
80 | * fortunately don't get interpreted as two arguments). | 80 | * fortunately don't get interpreted as two arguments). |
81 | */ | 81 | */ |
82 | #define RELOC(x) (x) | ||
83 | #define ADDR(x) (u32)(unsigned long)(x) | ||
84 | |||
82 | #ifdef CONFIG_PPC64 | 85 | #ifdef CONFIG_PPC64 |
83 | #define RELOC(x) (*PTRRELOC(&(x))) | ||
84 | #define ADDR(x) (u32) add_reloc_offset((unsigned long)(x)) | ||
85 | #define OF_WORKAROUNDS 0 | 86 | #define OF_WORKAROUNDS 0 |
86 | #else | 87 | #else |
87 | #define RELOC(x) (x) | ||
88 | #define ADDR(x) (u32) (x) | ||
89 | #define OF_WORKAROUNDS of_workarounds | 88 | #define OF_WORKAROUNDS of_workarounds |
90 | int of_workarounds; | 89 | int of_workarounds; |
91 | #endif | 90 | #endif |
@@ -334,9 +333,6 @@ static void __init prom_printf(const char *format, ...) | |||
334 | struct prom_t *_prom = &RELOC(prom); | 333 | struct prom_t *_prom = &RELOC(prom); |
335 | 334 | ||
336 | va_start(args, format); | 335 | va_start(args, format); |
337 | #ifdef CONFIG_PPC64 | ||
338 | format = PTRRELOC(format); | ||
339 | #endif | ||
340 | for (p = format; *p != 0; p = q) { | 336 | for (p = format; *p != 0; p = q) { |
341 | for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q) | 337 | for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q) |
342 | ; | 338 | ; |
@@ -437,9 +433,6 @@ static unsigned int __init prom_claim(unsigned long virt, unsigned long size, | |||
437 | 433 | ||
438 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) | 434 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) |
439 | { | 435 | { |
440 | #ifdef CONFIG_PPC64 | ||
441 | reason = PTRRELOC(reason); | ||
442 | #endif | ||
443 | prom_print(reason); | 436 | prom_print(reason); |
444 | /* Do not call exit because it clears the screen on pmac | 437 | /* Do not call exit because it clears the screen on pmac |
445 | * it also causes some sort of double-fault on early pmacs */ | 438 | * it also causes some sort of double-fault on early pmacs */ |
@@ -929,7 +922,7 @@ static void __init prom_send_capabilities(void) | |||
929 | * (we assume this is the same for all cores) and use it to | 922 | * (we assume this is the same for all cores) and use it to |
930 | * divide NR_CPUS. | 923 | * divide NR_CPUS. |
931 | */ | 924 | */ |
932 | cores = (u32 *)PTRRELOC(&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]); | 925 | cores = (u32 *)&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]; |
933 | if (*cores != NR_CPUS) { | 926 | if (*cores != NR_CPUS) { |
934 | prom_printf("WARNING ! " | 927 | prom_printf("WARNING ! " |
935 | "ibm_architecture_vec structure inconsistent: %lu!\n", | 928 | "ibm_architecture_vec structure inconsistent: %lu!\n", |
@@ -2850,6 +2843,53 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | |||
2850 | #endif /* CONFIG_BLK_DEV_INITRD */ | 2843 | #endif /* CONFIG_BLK_DEV_INITRD */ |
2851 | } | 2844 | } |
2852 | 2845 | ||
2846 | #ifdef CONFIG_PPC64 | ||
2847 | #ifdef CONFIG_RELOCATABLE | ||
2848 | static void reloc_toc(void) | ||
2849 | { | ||
2850 | } | ||
2851 | |||
2852 | static void unreloc_toc(void) | ||
2853 | { | ||
2854 | } | ||
2855 | #else | ||
2856 | static void __reloc_toc(void *tocstart, unsigned long offset, | ||
2857 | unsigned long nr_entries) | ||
2858 | { | ||
2859 | unsigned long i; | ||
2860 | unsigned long *toc_entry = (unsigned long *)tocstart; | ||
2861 | |||
2862 | for (i = 0; i < nr_entries; i++) { | ||
2863 | *toc_entry = *toc_entry + offset; | ||
2864 | toc_entry++; | ||
2865 | } | ||
2866 | } | ||
2867 | |||
2868 | static void reloc_toc(void) | ||
2869 | { | ||
2870 | unsigned long offset = reloc_offset(); | ||
2871 | unsigned long nr_entries = | ||
2872 | (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long); | ||
2873 | |||
2874 | /* Need to add offset to get at __prom_init_toc_start */ | ||
2875 | __reloc_toc(__prom_init_toc_start + offset, offset, nr_entries); | ||
2876 | |||
2877 | mb(); | ||
2878 | } | ||
2879 | |||
2880 | static void unreloc_toc(void) | ||
2881 | { | ||
2882 | unsigned long offset = reloc_offset(); | ||
2883 | unsigned long nr_entries = | ||
2884 | (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long); | ||
2885 | |||
2886 | mb(); | ||
2887 | |||
2888 | /* __prom_init_toc_start has been relocated, no need to add offset */ | ||
2889 | __reloc_toc(__prom_init_toc_start, -offset, nr_entries); | ||
2890 | } | ||
2891 | #endif | ||
2892 | #endif | ||
2853 | 2893 | ||
2854 | /* | 2894 | /* |
2855 | * We enter here early on, when the Open Firmware prom is still | 2895 | * We enter here early on, when the Open Firmware prom is still |
@@ -2867,6 +2907,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2867 | #ifdef CONFIG_PPC32 | 2907 | #ifdef CONFIG_PPC32 |
2868 | unsigned long offset = reloc_offset(); | 2908 | unsigned long offset = reloc_offset(); |
2869 | reloc_got2(offset); | 2909 | reloc_got2(offset); |
2910 | #else | ||
2911 | reloc_toc(); | ||
2870 | #endif | 2912 | #endif |
2871 | 2913 | ||
2872 | _prom = &RELOC(prom); | 2914 | _prom = &RELOC(prom); |
@@ -3061,6 +3103,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3061 | 3103 | ||
3062 | #ifdef CONFIG_PPC32 | 3104 | #ifdef CONFIG_PPC32 |
3063 | reloc_got2(-offset); | 3105 | reloc_got2(-offset); |
3106 | #else | ||
3107 | unreloc_toc(); | ||
3064 | #endif | 3108 | #endif |
3065 | 3109 | ||
3066 | #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL | 3110 | #ifdef CONFIG_PPC_EARLY_DEBUG_OPAL |
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh index 70f4286eaa7a..3765da6be4f2 100644 --- a/arch/powerpc/kernel/prom_init_check.sh +++ b/arch/powerpc/kernel/prom_init_check.sh | |||
@@ -22,7 +22,7 @@ __secondary_hold_acknowledge __secondary_hold_spinloop __start | |||
22 | strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224 | 22 | strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224 |
23 | reloc_got2 kernstart_addr memstart_addr linux_banner _stext | 23 | reloc_got2 kernstart_addr memstart_addr linux_banner _stext |
24 | opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry | 24 | opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry |
25 | boot_command_line" | 25 | boot_command_line __prom_init_toc_start __prom_init_toc_end" |
26 | 26 | ||
27 | NM="$1" | 27 | NM="$1" |
28 | OBJ="$2" | 28 | OBJ="$2" |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 65d1c08cf09e..654e479802f2 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -218,6 +218,11 @@ SECTIONS | |||
218 | 218 | ||
219 | .got : AT(ADDR(.got) - LOAD_OFFSET) { | 219 | .got : AT(ADDR(.got) - LOAD_OFFSET) { |
220 | __toc_start = .; | 220 | __toc_start = .; |
221 | #ifndef CONFIG_RELOCATABLE | ||
222 | __prom_init_toc_start = .; | ||
223 | arch/powerpc/kernel/prom_init.o*(.toc .got) | ||
224 | __prom_init_toc_end = .; | ||
225 | #endif | ||
221 | *(.got) | 226 | *(.got) |
222 | *(.toc) | 227 | *(.toc) |
223 | } | 228 | } |