Commit 378bac82 authored by Thomas Koeller's avatar Thomas Koeller Committed by Linus Torvalds

[PATCH] flush icache early when loading module

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: default avatarThomas Koeller <thomas@koeller.dyndns.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 19b4946c
...@@ -1509,6 +1509,7 @@ static struct module *load_module(void __user *umod, ...@@ -1509,6 +1509,7 @@ static struct module *load_module(void __user *umod,
long err = 0; long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
struct exception_table_entry *extable; struct exception_table_entry *extable;
mm_segment_t old_fs;
DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
umod, len, uargs); umod, len, uargs);
...@@ -1779,6 +1780,24 @@ static struct module *load_module(void __user *umod, ...@@ -1779,6 +1780,24 @@ static struct module *load_module(void __user *umod,
if (err < 0) if (err < 0)
goto cleanup; 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; mod->args = args;
if (obsparmindex) { if (obsparmindex) {
err = obsolete_params(mod->name, mod->args, err = obsolete_params(mod->name, mod->args,
...@@ -1860,7 +1879,6 @@ sys_init_module(void __user *umod, ...@@ -1860,7 +1879,6 @@ sys_init_module(void __user *umod,
const char __user *uargs) const char __user *uargs)
{ {
struct module *mod; struct module *mod;
mm_segment_t old_fs = get_fs();
int ret = 0; int ret = 0;
/* Must have permission */ /* Must have permission */
...@@ -1878,19 +1896,6 @@ sys_init_module(void __user *umod, ...@@ -1878,19 +1896,6 @@ sys_init_module(void __user *umod,
return PTR_ERR(mod); 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 /* Now sew it into the lists. They won't access us, since
strong_try_module_get() will fail. */ strong_try_module_get() will fail. */
stop_machine_run(__link_module, mod, NR_CPUS); stop_machine_run(__link_module, mod, NR_CPUS);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment