aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-powerpc
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-10-19 21:47:18 -0400
committerPaul Mackerras <paulus@samba.org>2006-10-24 21:54:07 -0400
commit0909c8c2d547e45ca50e2492b08ec93a37b35237 (patch)
tree23e66e1dc9a5bd674ba1375b5fccd2cb0d5787a8 /include/asm-powerpc
parent7aeb732428fc8e2ecae6d432873770c12f04a979 (diff)
[POWERPC] Support feature fixups in vdso's
This patch reworks the feature fixup mecanism so vdso's can be fixed up. The main issue was that the construct: .long label (or .llong on 64 bits) will not work in the case of a shared library like the vdso. It will generate an empty placeholder in the fixup table along with a reloc, which is not something we can deal with in the vdso. The idea here (thanks Alan Modra !) is to instead use something like: 1: .long label - 1b That is, the feature fixup tables no longer contain addresses of bits of code to patch, but offsets of such code from the fixup table entry itself. That is properly resolved by ld when building the .so's. I've modified the fixup mecanism generically to use that method for the rest of the kernel as well. Another trick is that the 32 bits vDSO included in the 64 bits kernel need to have a table in the 64 bits format. However, gas does not support 32 bits code with a statement of the form: .llong label - 1b (Or even just .llong label) That is, it cannot emit the right fixup/relocation for the linker to use to assign a 32 bits address to an .llong field. Thus, in the specific case of the 32 bits vdso built as part of the 64 bits kernel, we are using a modified macro that generates: .long 0xffffffff .llong label - 1b Note that is assumes that the value is negative which is enforced by the .lds (those offsets are always negative as the .text is always before the fixup table and gas doesn't support emiting the reloc the other way around). Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'include/asm-powerpc')
-rw-r--r--include/asm-powerpc/asm-compat.h52
-rw-r--r--include/asm-powerpc/cputable.h31
-rw-r--r--include/asm-powerpc/firmware.h15
-rw-r--r--include/asm-powerpc/timex.h8
4 files changed, 67 insertions, 39 deletions
diff --git a/include/asm-powerpc/asm-compat.h b/include/asm-powerpc/asm-compat.h
index 8e64be0cc47d..c89bd58ee283 100644
--- a/include/asm-powerpc/asm-compat.h
+++ b/include/asm-powerpc/asm-compat.h
@@ -14,6 +14,58 @@
14# define ASM_CONST(x) __ASM_CONST(x) 14# define ASM_CONST(x) __ASM_CONST(x)
15#endif 15#endif
16 16
17
18/*
19 * Feature section common macros
20 *
21 * Note that the entries now contain offsets between the table entry
22 * and the code rather than absolute code pointers in order to be
23 * useable with the vdso shared library. There is also an assumption
24 * that values will be negative, that is, the fixup table has to be
25 * located after the code it fixes up.
26 */
27#ifdef CONFIG_PPC64
28#ifdef __powerpc64__
29/* 64 bits kernel, 64 bits code */
30#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \
3199: \
32 .section sect,"a"; \
33 .align 3; \
3498: \
35 .llong msk; \
36 .llong val; \
37 .llong label##b-98b; \
38 .llong 99b-98b; \
39 .previous
40#else /* __powerpc64__ */
41/* 64 bits kernel, 32 bits code (ie. vdso32) */
42#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \
4399: \
44 .section sect,"a"; \
45 .align 3; \
4698: \
47 .llong msk; \
48 .llong val; \
49 .long 0xffffffff; \
50 .long label##b-98b; \
51 .long 0xffffffff; \
52 .long 99b-98b; \
53 .previous
54#endif /* !__powerpc64__ */
55#else /* CONFIG_PPC64 */
56/* 32 bits kernel, 32 bits code */
57#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \
5899: \
59 .section sect,"a"; \
60 .align 2; \
6198: \
62 .long msk; \
63 .long val; \
64 .long label##b-98b; \
65 .long 99b-98b; \
66 .previous
67#endif /* !CONFIG_PPC64 */
68
17#ifdef __powerpc64__ 69#ifdef __powerpc64__
18 70
19/* operations for longs and pointers */ 71/* operations for longs and pointers */
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 65faf322ace0..02e52d68cbbe 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -92,8 +92,8 @@ extern struct cpu_spec *cur_cpu_spec;
92extern unsigned int __start___ftr_fixup, __stop___ftr_fixup; 92extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
93 93
94extern struct cpu_spec *identify_cpu(unsigned long offset); 94extern struct cpu_spec *identify_cpu(unsigned long offset);
95extern void do_feature_fixups(unsigned long offset, unsigned long value, 95extern void do_feature_fixups(unsigned long value, void *fixup_start,
96 void *fixup_start, void *fixup_end); 96 void *fixup_end);
97 97
98#endif /* __ASSEMBLY__ */ 98#endif /* __ASSEMBLY__ */
99 99
@@ -435,32 +435,11 @@ static inline int cpu_has_feature(unsigned long feature)
435#ifdef __ASSEMBLY__ 435#ifdef __ASSEMBLY__
436 436
437#define BEGIN_FTR_SECTION_NESTED(label) label: 437#define BEGIN_FTR_SECTION_NESTED(label) label:
438#define BEGIN_FTR_SECTION BEGIN_FTR_SECTION_NESTED(98) 438#define BEGIN_FTR_SECTION BEGIN_FTR_SECTION_NESTED(97)
439
440#ifndef __powerpc64__
441#define END_FTR_SECTION_NESTED(msk, val, label) \
44299: \
443 .section __ftr_fixup,"a"; \
444 .align 2; \
445 .long msk; \
446 .long val; \
447 .long label##b; \
448 .long 99b; \
449 .previous
450#else /* __powerpc64__ */
451#define END_FTR_SECTION_NESTED(msk, val, label) \ 439#define END_FTR_SECTION_NESTED(msk, val, label) \
45299: \ 440 MAKE_FTR_SECTION_ENTRY(msk, val, label, __ftr_fixup)
453 .section __ftr_fixup,"a"; \
454 .align 3; \
455 .llong msk; \
456 .llong val; \
457 .llong label##b; \
458 .llong 99b; \
459 .previous
460#endif /* __powerpc64__ */
461
462#define END_FTR_SECTION(msk, val) \ 441#define END_FTR_SECTION(msk, val) \
463 END_FTR_SECTION_NESTED(msk, val, 98) 442 END_FTR_SECTION_NESTED(msk, val, 97)
464 443
465#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) 444#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk))
466#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) 445#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0)
diff --git a/include/asm-powerpc/firmware.h b/include/asm-powerpc/firmware.h
index c16e0a6b9dab..fdf9aff71150 100644
--- a/include/asm-powerpc/firmware.h
+++ b/include/asm-powerpc/firmware.h
@@ -100,17 +100,12 @@ extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup;
100 100
101#else /* __ASSEMBLY__ */ 101#else /* __ASSEMBLY__ */
102 102
103#define BEGIN_FW_FTR_SECTION 96: 103#define BEGIN_FW_FTR_SECTION_NESTED(label) label:
104 104#define BEGIN_FW_FTR_SECTION BEGIN_FW_FTR_SECTION_NESTED(97)
105#define END_FW_FTR_SECTION_NESTED(msk, val, label) \
106 MAKE_FTR_SECTION_ENTRY(msk, val, label, __fw_ftr_fixup)
105#define END_FW_FTR_SECTION(msk, val) \ 107#define END_FW_FTR_SECTION(msk, val) \
10697: \ 108 END_FW_FTR_SECTION_NESTED(msk, val, 97)
107 .section __fw_ftr_fixup,"a"; \
108 .align 3; \
109 .llong msk; \
110 .llong val; \
111 .llong 96b; \
112 .llong 97b; \
113 .previous
114 109
115#define END_FW_FTR_SECTION_IFSET(msk) END_FW_FTR_SECTION((msk), (msk)) 110#define END_FW_FTR_SECTION_IFSET(msk) END_FW_FTR_SECTION((msk), (msk))
116#define END_FW_FTR_SECTION_IFCLR(msk) END_FW_FTR_SECTION((msk), 0) 111#define END_FW_FTR_SECTION_IFCLR(msk) END_FW_FTR_SECTION((msk), 0)
diff --git a/include/asm-powerpc/timex.h b/include/asm-powerpc/timex.h
index 3b9a8e786806..e3f08cf91486 100644
--- a/include/asm-powerpc/timex.h
+++ b/include/asm-powerpc/timex.h
@@ -30,13 +30,15 @@ static inline cycles_t get_cycles(void)
30 ret = 0; 30 ret = 0;
31 31
32 __asm__ __volatile__( 32 __asm__ __volatile__(
33 "98: mftb %0\n" 33 "97: mftb %0\n"
34 "99:\n" 34 "99:\n"
35 ".section __ftr_fixup,\"a\"\n" 35 ".section __ftr_fixup,\"a\"\n"
36 ".align 2\n"
37 "98:\n"
36 " .long %1\n" 38 " .long %1\n"
37 " .long 0\n" 39 " .long 0\n"
38 " .long 98b\n" 40 " .long 97b-98b\n"
39 " .long 99b\n" 41 " .long 99b-98b\n"
40 ".previous" 42 ".previous"
41 : "=r" (ret) : "i" (CPU_FTR_601)); 43 : "=r" (ret) : "i" (CPU_FTR_601));
42#endif 44#endif