1
0
Fork 0

[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>
hifive-unleashed-5.1
Thomas Koeller 2005-09-06 15:17:11 -07:00 committed by Linus Torvalds
parent 19b4946ca9
commit 378bac820b
1 changed files with 19 additions and 14 deletions

View 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);