[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: 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>
This commit is contained in:
parent
19b4946ca9
commit
378bac820b
1 changed files with 19 additions and 14 deletions
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue