aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@vmware.com>2011-02-07 19:02:25 -0500
committerRusty Russell <rusty@rustcorp.com.au>2011-05-19 03:25:24 -0400
commitb4bc842802db3314f9a657094da0450a903ea619 (patch)
treedb9cadf46624dcd7e780850e8bda34b569a229b0
parent61c4f2c81c61f73549928dfd9f3e8f26aa36a8cf (diff)
module: deal with alignment issues in built-in module versions
On m68k natural alignment is 2-byte boundary but we are trying to align structures in __modver section on sizeof(void *) boundary. This causes trouble when we try to access elements in this section in array-like fashion when create "version" attributes for built-in modules. Moreover, as DaveM said, we can't reliably put structures into independent objects, put them into a special section, and then expect array access over them (via the section boundaries) after linking the objects together to just "work" due to variable alignment choices in different situations. The only solution that seems to work reliably is to make an array of plain pointers to the objects in question and put those pointers in the special section. Reported-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Dmitry Torokhov <dtor@vmware.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--include/linux/module.h10
-rw-r--r--kernel/params.c9
2 files changed, 11 insertions, 8 deletions
diff --git a/include/linux/module.h b/include/linux/module.h
index 5de42043dff0..4cfebc211695 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -174,10 +174,7 @@ extern struct module __this_module;
174#define MODULE_VERSION(_version) \ 174#define MODULE_VERSION(_version) \
175 extern ssize_t __modver_version_show(struct module_attribute *, \ 175 extern ssize_t __modver_version_show(struct module_attribute *, \
176 struct module *, char *); \ 176 struct module *, char *); \
177 static struct module_version_attribute __modver_version_attr \ 177 static struct module_version_attribute ___modver_attr = { \
178 __used \
179 __attribute__ ((__section__ ("__modver"),aligned(sizeof(void *)))) \
180 = { \
181 .mattr = { \ 178 .mattr = { \
182 .attr = { \ 179 .attr = { \
183 .name = "version", \ 180 .name = "version", \
@@ -187,7 +184,10 @@ extern struct module __this_module;
187 }, \ 184 }, \
188 .module_name = KBUILD_MODNAME, \ 185 .module_name = KBUILD_MODNAME, \
189 .version = _version, \ 186 .version = _version, \
190 } 187 }; \
188 static const struct module_version_attribute \
189 __used __attribute__ ((__section__ ("__modver"))) \
190 * __moduleparam_const __modver_attr = &___modver_attr
191#endif 191#endif
192 192
193/* Optional firmware file (or files) needed by the module 193/* Optional firmware file (or files) needed by the module
diff --git a/kernel/params.c b/kernel/params.c
index 7ab388a48a2e..28c5d5c83f6b 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -821,15 +821,18 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
821 return sprintf(buf, "%s\n", vattr->version); 821 return sprintf(buf, "%s\n", vattr->version);
822} 822}
823 823
824extern struct module_version_attribute __start___modver[], __stop___modver[]; 824extern const struct module_version_attribute *__start___modver[];
825extern const struct module_version_attribute *__stop___modver[];
825 826
826static void __init version_sysfs_builtin(void) 827static void __init version_sysfs_builtin(void)
827{ 828{
828 const struct module_version_attribute *vattr; 829 const struct module_version_attribute **p;
829 struct module_kobject *mk; 830 struct module_kobject *mk;
830 int err; 831 int err;
831 832
832 for (vattr = __start___modver; vattr < __stop___modver; vattr++) { 833 for (p = __start___modver; p < __stop___modver; p++) {
834 const struct module_version_attribute *vattr = *p;
835
833 mk = locate_module_kobject(vattr->module_name); 836 mk = locate_module_kobject(vattr->module_name);
834 if (mk) { 837 if (mk) {
835 err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr); 838 err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);