static initcall_t __initcall_##fn##id __used \
        __attribute__((__section__(".initcall" level ".init"))) = fn
 
+/*
+ * Early initcalls run before initializing SMP.
+ *
+ * Only for built-in code, not modules.
+ */
+#define early_initcall(fn)             __define_initcall("early",fn,early)
+
 /*
  * A "pure" initcall has no dependencies on anything else, and purely
  * initializes variables that couldn't be statically initialized.
 
 }
 
 
-extern initcall_t __initcall_start[], __initcall_end[];
+extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];
 
 static void __init do_initcalls(void)
 {
        initcall_t *call;
 
-       for (call = __initcall_start; call < __initcall_end; call++)
+       for (call = __early_initcall_end; call < __initcall_end; call++)
                do_one_initcall(*call);
 
        /* Make sure there is no pending stuff from the initcall sequence */
 }
 __setup("nosoftlockup", nosoftlockup_setup);
 
+static void __init __do_pre_smp_initcalls(void)
+{
+       initcall_t *call;
+
+       for (call = __initcall_start; call < __early_initcall_end; call++)
+               do_one_initcall(*call);
+}
+
 static void __init do_pre_smp_initcalls(void)
 {
        extern int spawn_ksoftirqd(void);
 
        smp_prepare_cpus(setup_max_cpus);
 
+       __do_pre_smp_initcalls();
        do_pre_smp_initcalls();
 
        smp_init();