diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2018-08-22 00:56:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-22 13:52:47 -0400 |
commit | 1b1eeca7e4c19fa76d409d4c7b338dba21f2df45 (patch) | |
tree | 6443f1ee2cdc661123076f02bda70dc25852045e | |
parent | 7290d58095712a89f845e1bca05334796dd49ed2 (diff) |
init: allow initcall tables to be emitted using relative references
Allow the initcall tables to be emitted using relative references that
are only half the size on 64-bit architectures and don't require fixups
at runtime on relocatable kernels.
Link: http://lkml.kernel.org/r/20180704083651.24360-5-ard.biesheuvel@linaro.org
Acked-by: James Morris <james.morris@microsoft.com>
Acked-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Acked-by: Petr Mladek <pmladek@suse.com>
Acked-by: Michael Ellerman <mpe@ellerman.id.au>
Acked-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morris <jmorris@namei.org>
Cc: Jessica Yu <jeyu@kernel.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Nicolas Pitre <nico@linaro.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Russell King <linux@armlinux.org.uk>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Garnier <thgarnie@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/init.h | 44 | ||||
-rw-r--r-- | init/main.c | 32 | ||||
-rw-r--r-- | kernel/printk/printk.c | 16 | ||||
-rw-r--r-- | security/security.c | 17 |
4 files changed, 68 insertions, 41 deletions
diff --git a/include/linux/init.h b/include/linux/init.h index bc27cf03c41e..2538d176dd1f 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
@@ -116,8 +116,24 @@ | |||
116 | typedef int (*initcall_t)(void); | 116 | typedef int (*initcall_t)(void); |
117 | typedef void (*exitcall_t)(void); | 117 | typedef void (*exitcall_t)(void); |
118 | 118 | ||
119 | extern initcall_t __con_initcall_start[], __con_initcall_end[]; | 119 | #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS |
120 | extern initcall_t __security_initcall_start[], __security_initcall_end[]; | 120 | typedef int initcall_entry_t; |
121 | |||
122 | static inline initcall_t initcall_from_entry(initcall_entry_t *entry) | ||
123 | { | ||
124 | return offset_to_ptr(entry); | ||
125 | } | ||
126 | #else | ||
127 | typedef initcall_t initcall_entry_t; | ||
128 | |||
129 | static inline initcall_t initcall_from_entry(initcall_entry_t *entry) | ||
130 | { | ||
131 | return *entry; | ||
132 | } | ||
133 | #endif | ||
134 | |||
135 | extern initcall_entry_t __con_initcall_start[], __con_initcall_end[]; | ||
136 | extern initcall_entry_t __security_initcall_start[], __security_initcall_end[]; | ||
121 | 137 | ||
122 | /* Used for contructor calls. */ | 138 | /* Used for contructor calls. */ |
123 | typedef void (*ctor_fn_t)(void); | 139 | typedef void (*ctor_fn_t)(void); |
@@ -167,9 +183,20 @@ extern bool initcall_debug; | |||
167 | * as KEEP() in the linker script. | 183 | * as KEEP() in the linker script. |
168 | */ | 184 | */ |
169 | 185 | ||
170 | #define __define_initcall(fn, id) \ | 186 | #ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS |
187 | #define ___define_initcall(fn, id, __sec) \ | ||
188 | __ADDRESSABLE(fn) \ | ||
189 | asm(".section \"" #__sec ".init\", \"a\" \n" \ | ||
190 | "__initcall_" #fn #id ": \n" \ | ||
191 | ".long " #fn " - . \n" \ | ||
192 | ".previous \n"); | ||
193 | #else | ||
194 | #define ___define_initcall(fn, id, __sec) \ | ||
171 | static initcall_t __initcall_##fn##id __used \ | 195 | static initcall_t __initcall_##fn##id __used \ |
172 | __attribute__((__section__(".initcall" #id ".init"))) = fn; | 196 | __attribute__((__section__(#__sec ".init"))) = fn; |
197 | #endif | ||
198 | |||
199 | #define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id) | ||
173 | 200 | ||
174 | /* | 201 | /* |
175 | * Early initcalls run before initializing SMP. | 202 | * Early initcalls run before initializing SMP. |
@@ -208,13 +235,8 @@ extern bool initcall_debug; | |||
208 | #define __exitcall(fn) \ | 235 | #define __exitcall(fn) \ |
209 | static exitcall_t __exitcall_##fn __exit_call = fn | 236 | static exitcall_t __exitcall_##fn __exit_call = fn |
210 | 237 | ||
211 | #define console_initcall(fn) \ | 238 | #define console_initcall(fn) ___define_initcall(fn,, .con_initcall) |
212 | static initcall_t __initcall_##fn \ | 239 | #define security_initcall(fn) ___define_initcall(fn,, .security_initcall) |
213 | __used __section(.con_initcall.init) = fn | ||
214 | |||
215 | #define security_initcall(fn) \ | ||
216 | static initcall_t __initcall_##fn \ | ||
217 | __used __section(.security_initcall.init) = fn | ||
218 | 240 | ||
219 | struct obs_kernel_param { | 241 | struct obs_kernel_param { |
220 | const char *str; | 242 | const char *str; |
diff --git a/init/main.c b/init/main.c index b729e1f22838..3a6ce89e128f 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -902,18 +902,18 @@ int __init_or_module do_one_initcall(initcall_t fn) | |||
902 | } | 902 | } |
903 | 903 | ||
904 | 904 | ||
905 | extern initcall_t __initcall_start[]; | 905 | extern initcall_entry_t __initcall_start[]; |
906 | extern initcall_t __initcall0_start[]; | 906 | extern initcall_entry_t __initcall0_start[]; |
907 | extern initcall_t __initcall1_start[]; | 907 | extern initcall_entry_t __initcall1_start[]; |
908 | extern initcall_t __initcall2_start[]; | 908 | extern initcall_entry_t __initcall2_start[]; |
909 | extern initcall_t __initcall3_start[]; | 909 | extern initcall_entry_t __initcall3_start[]; |
910 | extern initcall_t __initcall4_start[]; | 910 | extern initcall_entry_t __initcall4_start[]; |
911 | extern initcall_t __initcall5_start[]; | 911 | extern initcall_entry_t __initcall5_start[]; |
912 | extern initcall_t __initcall6_start[]; | 912 | extern initcall_entry_t __initcall6_start[]; |
913 | extern initcall_t __initcall7_start[]; | 913 | extern initcall_entry_t __initcall7_start[]; |
914 | extern initcall_t __initcall_end[]; | 914 | extern initcall_entry_t __initcall_end[]; |
915 | 915 | ||
916 | static initcall_t *initcall_levels[] __initdata = { | 916 | static initcall_entry_t *initcall_levels[] __initdata = { |
917 | __initcall0_start, | 917 | __initcall0_start, |
918 | __initcall1_start, | 918 | __initcall1_start, |
919 | __initcall2_start, | 919 | __initcall2_start, |
@@ -939,7 +939,7 @@ static char *initcall_level_names[] __initdata = { | |||
939 | 939 | ||
940 | static void __init do_initcall_level(int level) | 940 | static void __init do_initcall_level(int level) |
941 | { | 941 | { |
942 | initcall_t *fn; | 942 | initcall_entry_t *fn; |
943 | 943 | ||
944 | strcpy(initcall_command_line, saved_command_line); | 944 | strcpy(initcall_command_line, saved_command_line); |
945 | parse_args(initcall_level_names[level], | 945 | parse_args(initcall_level_names[level], |
@@ -950,7 +950,7 @@ static void __init do_initcall_level(int level) | |||
950 | 950 | ||
951 | trace_initcall_level(initcall_level_names[level]); | 951 | trace_initcall_level(initcall_level_names[level]); |
952 | for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) | 952 | for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++) |
953 | do_one_initcall(*fn); | 953 | do_one_initcall(initcall_from_entry(fn)); |
954 | } | 954 | } |
955 | 955 | ||
956 | static void __init do_initcalls(void) | 956 | static void __init do_initcalls(void) |
@@ -981,11 +981,11 @@ static void __init do_basic_setup(void) | |||
981 | 981 | ||
982 | static void __init do_pre_smp_initcalls(void) | 982 | static void __init do_pre_smp_initcalls(void) |
983 | { | 983 | { |
984 | initcall_t *fn; | 984 | initcall_entry_t *fn; |
985 | 985 | ||
986 | trace_initcall_level("early"); | 986 | trace_initcall_level("early"); |
987 | for (fn = __initcall_start; fn < __initcall0_start; fn++) | 987 | for (fn = __initcall_start; fn < __initcall0_start; fn++) |
988 | do_one_initcall(*fn); | 988 | do_one_initcall(initcall_from_entry(fn)); |
989 | } | 989 | } |
990 | 990 | ||
991 | /* | 991 | /* |
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 90b6ab01db59..918f386b2f6e 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c | |||
@@ -2788,7 +2788,8 @@ EXPORT_SYMBOL(unregister_console); | |||
2788 | void __init console_init(void) | 2788 | void __init console_init(void) |
2789 | { | 2789 | { |
2790 | int ret; | 2790 | int ret; |
2791 | initcall_t *call; | 2791 | initcall_t call; |
2792 | initcall_entry_t *ce; | ||
2792 | 2793 | ||
2793 | /* Setup the default TTY line discipline. */ | 2794 | /* Setup the default TTY line discipline. */ |
2794 | n_tty_init(); | 2795 | n_tty_init(); |
@@ -2797,13 +2798,14 @@ void __init console_init(void) | |||
2797 | * set up the console device so that later boot sequences can | 2798 | * set up the console device so that later boot sequences can |
2798 | * inform about problems etc.. | 2799 | * inform about problems etc.. |
2799 | */ | 2800 | */ |
2800 | call = __con_initcall_start; | 2801 | ce = __con_initcall_start; |
2801 | trace_initcall_level("console"); | 2802 | trace_initcall_level("console"); |
2802 | while (call < __con_initcall_end) { | 2803 | while (ce < __con_initcall_end) { |
2803 | trace_initcall_start((*call)); | 2804 | call = initcall_from_entry(ce); |
2804 | ret = (*call)(); | 2805 | trace_initcall_start(call); |
2805 | trace_initcall_finish((*call), ret); | 2806 | ret = call(); |
2806 | call++; | 2807 | trace_initcall_finish(call, ret); |
2808 | ce++; | ||
2807 | } | 2809 | } |
2808 | } | 2810 | } |
2809 | 2811 | ||
diff --git a/security/security.c b/security/security.c index 47cfff01d7ec..736e78da1ab9 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -48,14 +48,17 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = | |||
48 | static void __init do_security_initcalls(void) | 48 | static void __init do_security_initcalls(void) |
49 | { | 49 | { |
50 | int ret; | 50 | int ret; |
51 | initcall_t *call; | 51 | initcall_t call; |
52 | call = __security_initcall_start; | 52 | initcall_entry_t *ce; |
53 | |||
54 | ce = __security_initcall_start; | ||
53 | trace_initcall_level("security"); | 55 | trace_initcall_level("security"); |
54 | while (call < __security_initcall_end) { | 56 | while (ce < __security_initcall_end) { |
55 | trace_initcall_start((*call)); | 57 | call = initcall_from_entry(ce); |
56 | ret = (*call) (); | 58 | trace_initcall_start(call); |
57 | trace_initcall_finish((*call), ret); | 59 | ret = call(); |
58 | call++; | 60 | trace_initcall_finish(call, ret); |
61 | ce++; | ||
59 | } | 62 | } |
60 | } | 63 | } |
61 | 64 | ||