History

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.

Ard Biesheuvel committed 8 years ago

Commit 1b1eeca1 parent 7290d584 files · +68 −41Browse files

Unified · Split

4 files
  1. include/linux/init.h +33 −11
  2. init/main.c +16 −16
  3. kernel/printk/printk.c +9 −7
  4. security/security.c +10 −7
include/linux/init.h+33−11
@@ -116,8 +116,24 @@ · 115 unmodified lines
116typedef int (*initcall_t)(void);116typedef int (*initcall_t)(void);
117typedef void (*exitcall_t)(void);117typedef void (*exitcall_t)(void);
118 118
119extern initcall_t __con_initcall_start[], __con_initcall_end[];119#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
120extern initcall_t __security_initcall_start[], __security_initcall_end[];120typedef int initcall_entry_t;
121
122static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
123{
124 return offset_to_ptr(entry);
125}
126#else
127typedef initcall_t initcall_entry_t;
128
129static inline initcall_t initcall_from_entry(initcall_entry_t *entry)
130{
131 return *entry;
132}
133#endif
134
135extern initcall_entry_t __con_initcall_start[], __con_initcall_end[];
136extern initcall_entry_t __security_initcall_start[], __security_initcall_end[];
121 137
122/* Used for contructor calls. */138/* Used for contructor calls. */
123typedef void (*ctor_fn_t)(void);139typedef void (*ctor_fn_t)(void);
@@ -167,9 +183,20 @@ extern bool initcall_debug; · 43 unmodified lines
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; · 32 unmodified lines
208#define __exitcall(fn) \235#define __exitcall(fn) \
209 static exitcall_t __exitcall_##fn __exit_call = fn236 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
219struct obs_kernel_param {241struct obs_kernel_param {
220 const char *str;242 const char *str;
init/main.c+16−16
@@ -902,18 +902,18 @@ int __init_or_module do_one_initcall(initcall_t fn) · 901 unmodified lines
902}902}
903 903
904 904
905extern initcall_t __initcall_start[];905extern initcall_entry_t __initcall_start[];
906extern initcall_t __initcall0_start[];906extern initcall_entry_t __initcall0_start[];
907extern initcall_t __initcall1_start[];907extern initcall_entry_t __initcall1_start[];
908extern initcall_t __initcall2_start[];908extern initcall_entry_t __initcall2_start[];
909extern initcall_t __initcall3_start[];909extern initcall_entry_t __initcall3_start[];
910extern initcall_t __initcall4_start[];910extern initcall_entry_t __initcall4_start[];
911extern initcall_t __initcall5_start[];911extern initcall_entry_t __initcall5_start[];
912extern initcall_t __initcall6_start[];912extern initcall_entry_t __initcall6_start[];
913extern initcall_t __initcall7_start[];913extern initcall_entry_t __initcall7_start[];
914extern initcall_t __initcall_end[];914extern initcall_entry_t __initcall_end[];
915 915
916static initcall_t *initcall_levels[] __initdata = {916static 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 = { · 19 unmodified lines
939 939
940static void __init do_initcall_level(int level)940static 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) · 4 unmodified lines
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
956static void __init do_initcalls(void)956static void __init do_initcalls(void)
@@ -981,11 +981,11 @@ static void __init do_basic_setup(void) · 24 unmodified lines
981 981
982static void __init do_pre_smp_initcalls(void)982static 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/*
kernel/printk/printk.c+9−7
@@ -2788,7 +2788,8 @@ EXPORT_SYMBOL(unregister_console); · 2787 unmodified lines
2788void __init console_init(void)2788void __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) · 2 unmodified lines
2797 * set up the console device so that later boot sequences can2798 * 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
security/security.c+10−7
@@ -48,14 +48,17 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = · 47 unmodified lines
48static void __init do_security_initcalls(void)48static 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