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
116116 typedef int (*initcall_t)(void);
117117 typedef void (*exitcall_t)(void);
118118
119−extern initcall_t __con_initcall_start[], __con_initcall_end[];
120−extern initcall_t __security_initcall_start[], __security_initcall_end[];
119+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
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[];
121137
122138 /* Used for contructor calls. */
123139 typedef void (*ctor_fn_t)(void);
@@ -167,9 +183,20 @@ extern bool initcall_debug; · 43 unmodified lines
167183 * as KEEP() in the linker script.
168184 */
169185
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) \
171195 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)
173200
174201 /*
175202 * Early initcalls run before initializing SMP.
@@ -208,13 +235,8 @@ extern bool initcall_debug; · 32 unmodified lines
208235 #define __exitcall(fn) \
209236 static exitcall_t __exitcall_##fn __exit_call = fn
210237
211−#define console_initcall(fn) \
212− static initcall_t __initcall_##fn \
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
238+#define console_initcall(fn) ___define_initcall(fn,, .con_initcall)
239+#define security_initcall(fn) ___define_initcall(fn,, .security_initcall)
218240
219241 struct obs_kernel_param {
220242 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
902902 }
903903
904904
905−extern initcall_t __initcall_start[];
906−extern initcall_t __initcall0_start[];
907−extern initcall_t __initcall1_start[];
908−extern initcall_t __initcall2_start[];
909−extern initcall_t __initcall3_start[];
910−extern initcall_t __initcall4_start[];
911−extern initcall_t __initcall5_start[];
912−extern initcall_t __initcall6_start[];
913−extern initcall_t __initcall7_start[];
914−extern initcall_t __initcall_end[];
915−
916−static initcall_t *initcall_levels[] __initdata = {
905+extern initcall_entry_t __initcall_start[];
906+extern initcall_entry_t __initcall0_start[];
907+extern initcall_entry_t __initcall1_start[];
908+extern initcall_entry_t __initcall2_start[];
909+extern initcall_entry_t __initcall3_start[];
910+extern initcall_entry_t __initcall4_start[];
911+extern initcall_entry_t __initcall5_start[];
912+extern initcall_entry_t __initcall6_start[];
913+extern initcall_entry_t __initcall7_start[];
914+extern initcall_entry_t __initcall_end[];
915+
916+static initcall_entry_t *initcall_levels[] __initdata = {
917917 __initcall0_start,
918918 __initcall1_start,
919919 __initcall2_start,
@@ -939,7 +939,7 @@ static char *initcall_level_names[] __initdata = { · 19 unmodified lines
939939
940940 static void __init do_initcall_level(int level)
941941 {
942− initcall_t *fn;
942+ initcall_entry_t *fn;
943943
944944 strcpy(initcall_command_line, saved_command_line);
945945 parse_args(initcall_level_names[level],
@@ -950,7 +950,7 @@ static void __init do_initcall_level(int level) · 4 unmodified lines
950950
951951 trace_initcall_level(initcall_level_names[level]);
952952 for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
953− do_one_initcall(*fn);
953+ do_one_initcall(initcall_from_entry(fn));
954954 }
955955
956956 static void __init do_initcalls(void)
@@ -981,11 +981,11 @@ static void __init do_basic_setup(void) · 24 unmodified lines
981981
982982 static void __init do_pre_smp_initcalls(void)
983983 {
984− initcall_t *fn;
984+ initcall_entry_t *fn;
985985
986986 trace_initcall_level("early");
987987 for (fn = __initcall_start; fn < __initcall0_start; fn++)
988− do_one_initcall(*fn);
988+ do_one_initcall(initcall_from_entry(fn));
989989 }
990990
991991 /*
kernel/printk/printk.c+9−7
@@ -2788,7 +2788,8 @@ EXPORT_SYMBOL(unregister_console); · 2787 unmodified lines
27882788 void __init console_init(void)
27892789 {
27902790 int ret;
2791− initcall_t *call;
2791+ initcall_t call;
2792+ initcall_entry_t *ce;
27922793
27932794 /* Setup the default TTY line discipline. */
27942795 n_tty_init();
@@ -2797,13 +2798,14 @@ void __init console_init(void) · 2 unmodified lines
27972798 * set up the console device so that later boot sequences can
27982799 * inform about problems etc..
27992800 */
2800− call = __con_initcall_start;
2801+ ce = __con_initcall_start;
28012802 trace_initcall_level("console");
2802− while (call < __con_initcall_end) {
2803− trace_initcall_start((*call));
2804− ret = (*call)();
2805− trace_initcall_finish((*call), ret);
2806− call++;
2803+ while (ce < __con_initcall_end) {
2804+ call = initcall_from_entry(ce);
2805+ trace_initcall_start(call);
2806+ ret = call();
2807+ trace_initcall_finish(call, ret);
2808+ ce++;
28072809 }
28082810 }
28092811
security/security.c+10−7
@@ -48,14 +48,17 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = · 47 unmodified lines
4848 static void __init do_security_initcalls(void)
4949 {
5050 int ret;
51− initcall_t *call;
52− call = __security_initcall_start;
51+ initcall_t call;
52+ initcall_entry_t *ce;
53+
54+ ce = __security_initcall_start;
5355 trace_initcall_level("security");
54− while (call < __security_initcall_end) {
55− trace_initcall_start((*call));
56− ret = (*call) ();
57− trace_initcall_finish((*call), ret);
58− call++;
56+ while (ce < __security_initcall_end) {
57+ call = initcall_from_entry(ce);
58+ trace_initcall_start(call);
59+ ret = call();
60+ trace_initcall_finish(call, ret);
61+ ce++;
5962 }
6063 }
6164