[PATCH] flush icache early when loading module
authorThomas Koeller <thomas@koeller.dyndns.org>
Tue, 6 Sep 2005 22:17:11 +0000 (15:17 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Wed, 7 Sep 2005 23:57:26 +0000 (16:57 -0700)
Change the sequence of operations performed during module loading to flush
the instruction cache before module parameters are processed.  If a module
has parameters of an unusual type that cannot be handled using the standard
accessor functions param_set_xxx and param_get_xxx, it has to to provide a
set of accessor functions for this type.  This requires module code to be
executed during parameter processing, which is of course only possible
after the icache has been flushed.

Signed-off-by: Thomas Koeller <thomas@koeller.dyndns.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
kernel/module.c

index c32995fbd8fd14b608bb49e5b0f5899e41ffd979..4b39d3793c720673452b6d8be18ade674360131a 100644 (file)
@@ -1509,6 +1509,7 @@ static struct module *load_module(void __user *umod,
        long err = 0;
        void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
        struct exception_table_entry *extable;
+       mm_segment_t old_fs;
 
        DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
               umod, len, uargs);
@@ -1779,6 +1780,24 @@ static struct module *load_module(void __user *umod,
        if (err < 0)
                goto cleanup;
 
+       /* flush the icache in correct context */
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       /*
+        * Flush the instruction cache, since we've played with text.
+        * Do it before processing of module parameters, so the module
+        * can provide parameter accessor functions of its own.
+        */
+       if (mod->module_init)
+               flush_icache_range((unsigned long)mod->module_init,
+                                  (unsigned long)mod->module_init
+                                  + mod->init_size);
+       flush_icache_range((unsigned long)mod->module_core,
+                          (unsigned long)mod->module_core + mod->core_size);
+
+       set_fs(old_fs);
+
        mod->args = args;
        if (obsparmindex) {
                err = obsolete_params(mod->name, mod->args,
@@ -1860,7 +1879,6 @@ sys_init_module(void __user *umod,
                const char __user *uargs)
 {
        struct module *mod;
-       mm_segment_t old_fs = get_fs();
        int ret = 0;
 
        /* Must have permission */
@@ -1878,19 +1896,6 @@ sys_init_module(void __user *umod,
                return PTR_ERR(mod);
        }
 
-       /* flush the icache in correct context */
-       set_fs(KERNEL_DS);
-
-       /* Flush the instruction cache, since we've played with text */
-       if (mod->module_init)
-               flush_icache_range((unsigned long)mod->module_init,
-                                  (unsigned long)mod->module_init
-                                  + mod->init_size);
-       flush_icache_range((unsigned long)mod->module_core,
-                          (unsigned long)mod->module_core + mod->core_size);
-
-       set_fs(old_fs);
-
        /* Now sew it into the lists.  They won't access us, since
            strong_try_module_get() will fail. */
        stop_machine_run(__link_module, mod, NR_CPUS);