aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorThomas Koeller <thomas@koeller.dyndns.org>2005-09-06 18:17:11 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:57:26 -0400
commit378bac820be6a0ec95df8151524de73ad2b2d2ac (patch)
tree457827b58dcbf923e151b08128d84c33d13c1149 /kernel
parent19b4946ca9d1e35d4c641dcebe27378de34f3ddd (diff)
[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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/module.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/kernel/module.c b/kernel/module.c
index c32995fbd8fd..4b39d3793c72 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1509,6 +1509,7 @@ static struct module *load_module(void __user *umod,
1509 long err = 0; 1509 long err = 0;
1510 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 1510 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
1511 struct exception_table_entry *extable; 1511 struct exception_table_entry *extable;
1512 mm_segment_t old_fs;
1512 1513
1513 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", 1514 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
1514 umod, len, uargs); 1515 umod, len, uargs);
@@ -1779,6 +1780,24 @@ static struct module *load_module(void __user *umod,
1779 if (err < 0) 1780 if (err < 0)
1780 goto cleanup; 1781 goto cleanup;
1781 1782
1783 /* flush the icache in correct context */
1784 old_fs = get_fs();
1785 set_fs(KERNEL_DS);
1786
1787 /*
1788 * Flush the instruction cache, since we've played with text.
1789 * Do it before processing of module parameters, so the module
1790 * can provide parameter accessor functions of its own.
1791 */
1792 if (mod->module_init)
1793 flush_icache_range((unsigned long)mod->module_init,
1794 (unsigned long)mod->module_init
1795 + mod->init_size);
1796 flush_icache_range((unsigned long)mod->module_core,
1797 (unsigned long)mod->module_core + mod->core_size);
1798
1799 set_fs(old_fs);
1800
1782 mod->args = args; 1801 mod->args = args;
1783 if (obsparmindex) { 1802 if (obsparmindex) {
1784 err = obsolete_params(mod->name, mod->args, 1803 err = obsolete_params(mod->name, mod->args,
@@ -1860,7 +1879,6 @@ sys_init_module(void __user *umod,
1860 const char __user *uargs) 1879 const char __user *uargs)
1861{ 1880{
1862 struct module *mod; 1881 struct module *mod;
1863 mm_segment_t old_fs = get_fs();
1864 int ret = 0; 1882 int ret = 0;
1865 1883
1866 /* Must have permission */ 1884 /* Must have permission */
@@ -1878,19 +1896,6 @@ sys_init_module(void __user *umod,
1878 return PTR_ERR(mod); 1896 return PTR_ERR(mod);
1879 } 1897 }
1880 1898
1881 /* flush the icache in correct context */
1882 set_fs(KERNEL_DS);
1883
1884 /* Flush the instruction cache, since we've played with text */
1885 if (mod->module_init)
1886 flush_icache_range((unsigned long)mod->module_init,
1887 (unsigned long)mod->module_init
1888 + mod->init_size);
1889 flush_icache_range((unsigned long)mod->module_core,
1890 (unsigned long)mod->module_core + mod->core_size);
1891
1892 set_fs(old_fs);
1893
1894 /* Now sew it into the lists. They won't access us, since 1899 /* Now sew it into the lists. They won't access us, since
1895 strong_try_module_get() will fail. */ 1900 strong_try_module_get() will fail. */
1896 stop_machine_run(__link_module, mod, NR_CPUS); 1901 stop_machine_run(__link_module, mod, NR_CPUS);