Commit 378bac820be6a0ec95df8151524de73ad2b2d2ac
Committed by
Linus Torvalds
1 parent
19b4946ca9
Exists in
master
and in
7 other branches
[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>
Showing 1 changed file with 19 additions and 14 deletions Side-by-side Diff
kernel/module.c
... | ... | @@ -1509,6 +1509,7 @@ |
1509 | 1509 | long err = 0; |
1510 | 1510 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ |
1511 | 1511 | struct exception_table_entry *extable; |
1512 | + mm_segment_t old_fs; | |
1512 | 1513 | |
1513 | 1514 | DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", |
1514 | 1515 | umod, len, uargs); |
... | ... | @@ -1779,6 +1780,24 @@ |
1779 | 1780 | if (err < 0) |
1780 | 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 | 1801 | mod->args = args; |
1783 | 1802 | if (obsparmindex) { |
1784 | 1803 | err = obsolete_params(mod->name, mod->args, |
... | ... | @@ -1860,7 +1879,6 @@ |
1860 | 1879 | const char __user *uargs) |
1861 | 1880 | { |
1862 | 1881 | struct module *mod; |
1863 | - mm_segment_t old_fs = get_fs(); | |
1864 | 1882 | int ret = 0; |
1865 | 1883 | |
1866 | 1884 | /* Must have permission */ |
... | ... | @@ -1877,19 +1895,6 @@ |
1877 | 1895 | up(&module_mutex); |
1878 | 1896 | return PTR_ERR(mod); |
1879 | 1897 | } |
1880 | - | |
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 | 1898 | |
1894 | 1899 | /* Now sew it into the lists. They won't access us, since |
1895 | 1900 | strong_try_module_get() will fail. */ |