Skip to contentSkip to conversation

module: deal with alignment issues in built-in module versions

PATCH Superseded Dmitry Torokhov 7 participants 33 messages Feb 8, 2011 – Feb 23, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/3 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.

---
 include/linux/module.h |   10 +++++-----
 kernel/params.c        |    9 ++++++---
 2 files changed, 11 insertions(+), 8 deletions(-)
include/linux/module.h +5 -5
index 9bdf27c..9b7081a 100644
@@ -174,10 +174,7 @@ extern struct module __this_module;
 #define MODULE_VERSION(_version)					\
 	extern ssize_t __modver_version_show(struct module_attribute *,	\
 					     struct module *, char *);	\
-	static struct module_version_attribute __modver_version_attr	\
-	__used								\
-    __attribute__ ((__section__ ("__modver"),aligned(sizeof(void *)))) \
-	= {								\
+	static struct module_version_attribute ___modver_attr = {	\
 		.mattr	= {						\
 			.attr	= {					\
 				.name	= "version",			\
@@ -187,7 +184,10 @@ extern struct module __this_module;
 		},							\
 		.module_name	= KBUILD_MODNAME,			\
 		.version	= _version,				\
-	}
+	};								\
+	static const struct module_version_attribute			\
+	__used __attribute__ ((__section__ ("__modver")))		\
+	* __moduleparam_const __modver_attr = &___modver_attr
 #endif
 
 /* Optional firmware file (or files) needed by the module
kernel/params.c +6 -3
index 0da1411..09a08cb 100644
@@ -821,15 +821,18 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
 	return sprintf(buf, "%s\n", vattr->version);
 }
 
-extern struct module_version_attribute __start___modver[], __stop___modver[];
+extern const struct module_version_attribute *__start___modver[];
+extern const struct module_version_attribute *__stop___modver[];
 
 static void __init version_sysfs_builtin(void)
 {
-	const struct module_version_attribute *vattr;
+	const struct module_version_attribute **p;
 	struct module_kobject *mk;
 	int err;
 
-	for (vattr = __start___modver; vattr < __stop___modver; vattr++) {
+	for (p = __start___modver; p < __stop___modver; p++) {
+		const struct module_version_attribute *vattr = *p;
+
 		mk = locate_module_kobject(vattr->module_name);
 		if (mk) {
 			err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
Signature · 1 line
1.7.3.2
#1 lore raw

PATCH 2/3 module: deal with alignment issues in built-in module parameters

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.

---
 include/linux/moduleparam.h |   14 ++++++++------
 kernel/params.c             |   10 ++++++----
 2 files changed, 14 insertions(+), 10 deletions(-)
include/linux/moduleparam.h +8 -6
index 07b4195..05b92c0 100644
@@ -147,15 +147,17 @@ struct kparam_array
 	BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2))	\
 	+ BUILD_BUG_ON_ZERO(sizeof(""prefix) > MAX_PARAM_PREFIX_LEN);	\
 	static const char __param_str_##name[] = prefix #name;		\
-	static struct kernel_param __moduleparam_const __param_##name	\
-	__used								\
-    __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
-	= { __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0,	\
-	    { arg } }
+	static const struct kernel_param ___param_##name = {		\
+	    __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0,	\
+	    { arg }							\
+	};								\
+	static const struct kernel_param				\
+	__used __attribute__ ((__section__ ("__param")))		\
+	* __moduleparam_const __param_##name = &___param_##name
 
 /* Obsolete - use module_param_cb() */
 #define module_param_call(name, set, get, arg, perm)			\
-	static struct kernel_param_ops __param_ops_##name =		\
+	static const struct kernel_param_ops __param_ops_##name =	\
 		 { (void *)set, (void *)get };				\
 	__module_param_call(MODULE_PARAM_PREFIX,			\
 			    name, &__param_ops_##name, arg,		\
kernel/params.c +6 -4
index 09a08cb..66f7e66 100644
@@ -498,7 +498,8 @@ EXPORT_SYMBOL(param_ops_string);
 #define to_module_attr(n) container_of(n, struct module_attribute, attr)
 #define to_module_kobject(n) container_of(n, struct module_kobject, kobj)
 
-extern struct kernel_param __start___param[], __stop___param[];
+extern const struct kernel_param *__start___param[];
+extern const struct kernel_param *__stop___param[];
 
 struct param_attribute
 {
@@ -754,7 +755,7 @@ static struct module_kobject * __init locate_module_kobject(const char *name)
 }
 
 static void __init kernel_add_sysfs_param(const char *name,
-					  struct kernel_param *kparam,
+					  const struct kernel_param *kparam,
 					  unsigned int name_skip)
 {
 	struct module_kobject *mk;
@@ -789,11 +790,12 @@ static void __init kernel_add_sysfs_param(const char *name,
  */
 static void __init param_sysfs_builtin(void)
 {
-	struct kernel_param *kp;
+	const struct kernel_param **p;
 	unsigned int name_len;
 	char modname[MODULE_NAME_LEN];
 
-	for (kp = __start___param; kp < __stop___param; kp++) {
+	for (p = __start___param; p < __stop___param; p++) {
+		const struct kernel_param *kp = *p;
 		char *dot;
 
 		if (kp->perm == 0)
Signature · 1 line
1.7.3.2
#2 lore raw

PATCH 3/3 module: do not hide __modver_version_show declaration behind ifdef

In reply to Dmitry Torokhov

Doing so prevents the following warning from sparse:

CHECK kernel/params.c
kernel/params.c:817:9: warning: symbol '__modver_version_show' was not declared. Should it be static?

since kernel/params.c is never compiled with MODULE being set.

---
 include/linux/module.h |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
include/linux/module.h +3 -2
index 9b7081a..cb41837 100644
@@ -64,6 +64,9 @@ struct module_version_attribute {
 	const char *version;
 };
 
+extern ssize_t __modver_version_show(struct module_attribute *,
+				     struct module *, char *);
+
 struct module_kobject
 {
 	struct kobject kobj;
@@ -172,8 +175,6 @@ extern struct module __this_module;
 #define MODULE_VERSION(_version) MODULE_INFO(version, _version)
 #else
 #define MODULE_VERSION(_version)					\
-	extern ssize_t __modver_version_show(struct module_attribute *,	\
-					     struct module *, char *);	\
 	static struct module_version_attribute ___modver_attr = {	\
 		.mattr	= {						\
 			.attr	= {					\
Signature · 1 line
1.7.3.2
Tested-by on v1 1/3
#3 lore raw
In reply to Dmitry Torokhov
Quoted 14 lines · Dmitry Torokhov

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.

Quoted 2 lines

Thanks!

Quoted 67 lines

---
 include/linux/module.h |   10 +++++-----
 kernel/params.c        |    9 ++++++---

 2 files changed, 11 insertions(+), 8 deletions(-)
include/linux/module.h +5 -5
index 9bdf27c..9b7081a 100644
@@ -174,10 +174,7 @@ extern struct module __this_module;
  #define MODULE_VERSION(_version)                                       \
        extern ssize_t __modver_version_show(struct module_attribute *, \
                                             struct module *, char *);  \
-       static struct module_version_attribute __modver_version_attr    \
-       __used                                                          \
-    __attribute__ ((__section__ ("__modver"),aligned(sizeof(void *)))) \
-       = {                                                             \
+       static struct module_version_attribute ___modver_attr = {       \
                .mattr  = {                                             \
                        .attr   = {                                     \
                                .name   = "version",                    \
@@ -187,7 +184,10 @@ extern struct module __this_module;
                },                                                      \
                .module_name    = KBUILD_MODNAME,                       \
                .version        = _version,                             \
-       }
+       };                                                              \
+       static const struct module_version_attribute                    \
+       __used __attribute__ ((__section__ ("__modver")))               \
+       * __moduleparam_const __modver_attr = &___modver_attr
  #endif
 
  /* Optional firmware file (or files) needed by the module
kernel/params.c +6 -4
index 0da1411..09a08cb 100644
@@ -821,15 +821,18 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
        return sprintf(buf, "%s\n", vattr->version);
  }
 
-extern struct module_version_attribute __start___modver[], __stop___modver[];
+extern const struct module_version_attribute *__start___modver[];
+extern const struct module_version_attribute *__stop___modver[];
 
  static void __init version_sysfs_builtin(void)
  {
-       const struct module_version_attribute *vattr;
+       const struct module_version_attribute **p;
        struct module_kobject *mk;
        int err;
 
-       for (vattr = __start___modver; vattr < __stop___modver; vattr++) {
+       for (p = __start___modver; p < __stop___modver; p++) {
+               const struct module_version_attribute *vattr = *p;
+
                mk = locate_module_kobject(vattr->module_name);
                if (mk) {
                        err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
--

1.7.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-arch" in the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Signature · 10 lines
Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
#4 lore raw
Quoted 15 lines · Geert Uytterhoeven
Quoted 14 lines · Dmitry Torokhov

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.

Quoted 6 lines
Quoted 2 lines

Thanks!

Can we please get this in? 2.6.38-rc5 still crashes on m68k.

Thx!

Quoted 52 lines
Quoted 52 lines

---
 include/linux/module.h |   10 +++++-----
 kernel/params.c        |    9 ++++++---

 2 files changed, 11 insertions(+), 8 deletions(-)
include/linux/module.h +5 -5
index 9bdf27c..9b7081a 100644
@@ -174,10 +174,7 @@ extern struct module __this_module;
  #define MODULE_VERSION(_version)                                       \
        extern ssize_t __modver_version_show(struct module_attribute *, \
                                             struct module *, char *);  \
-       static struct module_version_attribute __modver_version_attr    \
-       __used                                                          \
-    __attribute__ ((__section__ ("__modver"),aligned(sizeof(void *)))) \
-       = {                                                             \
+       static struct module_version_attribute ___modver_attr = {       \
                .mattr  = {                                             \
                        .attr   = {                                     \
                                .name   = "version",                    \
@@ -187,7 +184,10 @@ extern struct module __this_module;
                },                                                      \
                .module_name    = KBUILD_MODNAME,                       \
                .version        = _version,                             \
-       }
+       };                                                              \
+       static const struct module_version_attribute                    \
+       __used __attribute__ ((__section__ ("__modver")))               \
+       * __moduleparam_const __modver_attr = &___modver_attr
  #endif
 
  /* Optional firmware file (or files) needed by the module
kernel/params.c +3 -2
index 0da1411..09a08cb 100644
@@ -821,15 +821,18 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
        return sprintf(buf, "%s\n", vattr->version);
  }
 
-extern struct module_version_attribute __start___modver[], __stop___modver[];
+extern const struct module_version_attribute *__start___modver[];
+extern const struct module_version_attribute *__stop___modver[];
 
  static void __init version_sysfs_builtin(void)
  {
-       const struct module_version_attribute *vattr;
+       const struct module_version_attribute **p;
        struct module_kobject *mk;
        int err;
 
Quoted 9 lines
Quoted 9 lines
kernel/params.c +3 -2
-       for (vattr = __start___modver; vattr < __stop___modver; vattr++) {
+       for (p = __start___modver; p < __stop___modver; p++) {
+               const struct module_version_attribute *vattr = *p;
+
                mk = locate_module_kobject(vattr->module_name);
                if (mk) {
                        err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
--

1.7.3.2

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds

#5 lore raw

PATCH v2 1/1 module: deal with alignment issues in built-in module parameters

In reply to Dmitry Torokhov
Quoted 1 line

From 03f1332fc02af7af0d06ab409e3ec72107637845 Mon Sep 17 00:00:00 2001

From: Dmitry Torokhov <[email protected]>
Date: Mon, 7 Feb 2011 13:47:20 -0800
Subject: [PATCH] module: deal with alignment issues in built-in module parameters

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.

---

This is v2 of the patch, hopefully fixing all the issues that were presented in the original submission, namely:

- fix for kparam_[un]block_sysfs_write() breakage;
- convert non-built-in module parameter case to expect array of pointers to struct kernel_param, not array of the structures themselves.

Thanks,

Dmitry

 include/linux/module.h      |    2 +-
 include/linux/moduleparam.h |   24 ++++++++++++----------
 init/main.c                 |    2 +-
 kernel/module.c             |    2 +-
 kernel/params.c             |   45 +++++++++++++++++++++++-------------------
 5 files changed, 41 insertions(+), 34 deletions(-)
include/linux/module.h +1 -1
index cb41837..c256380 100644
@@ -292,7 +292,7 @@ struct module
 	unsigned int num_syms;
 
 	/* Kernel parameters. */
-	struct kernel_param *kp;
+	const struct kernel_param **kp;
 	unsigned int num_kp;
 
 	/* GPL-only exported symbols. */
include/linux/moduleparam.h +13 -11
index 07b4195..f9de240 100644
@@ -147,15 +147,17 @@ struct kparam_array
 	BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2))	\
 	+ BUILD_BUG_ON_ZERO(sizeof(""prefix) > MAX_PARAM_PREFIX_LEN);	\
 	static const char __param_str_##name[] = prefix #name;		\
-	static struct kernel_param __moduleparam_const __param_##name	\
-	__used								\
-    __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
-	= { __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0,	\
-	    { arg } }
+	static const struct kernel_param __param_##name = {		\
+	    __param_str_##name, ops, perm, isbool ? KPARAM_ISBOOL : 0,	\
+	    { arg }							\
+	};								\
+	static const struct kernel_param				\
+	__used __attribute__ ((__section__ ("__param")))		\
+	* __moduleparam_const ___param_##name = &__param_##name
 
 /* Obsolete - use module_param_cb() */
 #define module_param_call(name, set, get, arg, perm)			\
-	static struct kernel_param_ops __param_ops_##name =		\
+	static const struct kernel_param_ops __param_ops_##name =	\
 		 { (void *)set, (void *)get };				\
 	__module_param_call(MODULE_PARAM_PREFIX,			\
 			    name, &__param_ops_##name, arg,		\
@@ -265,15 +267,15 @@ static inline void __kernel_param_unlock(void)
 /* Called on module insert or kernel boot */
 extern int parse_args(const char *name,
 		      char *args,
-		      const struct kernel_param *params,
+		      const struct kernel_param **params,
 		      unsigned num,
 		      int (*unknown)(char *param, char *val));
 
 /* Called by module remove. */
 #ifdef CONFIG_SYSFS
-extern void destroy_params(const struct kernel_param *params, unsigned num);
+extern void destroy_params(const struct kernel_param **params, unsigned num);
 #else
-static inline void destroy_params(const struct kernel_param *params,
+static inline void destroy_params(const struct kernel_param **params,
 				  unsigned num)
 {
 }
@@ -391,13 +393,13 @@ struct module;
 
 #if defined(CONFIG_SYSFS) && defined(CONFIG_MODULES)
 extern int module_param_sysfs_setup(struct module *mod,
-				    const struct kernel_param *kparam,
+				    const struct kernel_param **kparam,
 				    unsigned int num_params);
 
 extern void module_param_sysfs_remove(struct module *mod);
 #else
 static inline int module_param_sysfs_setup(struct module *mod,
-			     const struct kernel_param *kparam,
+			     const struct kernel_param **kparam,
 			     unsigned int num_params)
 {
 	return 0;
init/main.c +1 -1
index 33c37c3..3601586 100644
@@ -544,7 +544,7 @@ static void __init mm_init(void)
 asmlinkage void __init start_kernel(void)
 {
 	char * command_line;
-	extern const struct kernel_param __start___param[], __stop___param[];
+	extern const struct kernel_param *__start___param[], *__stop___param[];
 
 	smp_setup_processor_id();
 
kernel/module.c +1 -1
index efa290e..7c6c3bf 100644
@@ -1470,7 +1470,7 @@ out:
 
 static int mod_sysfs_setup(struct module *mod,
 			   const struct load_info *info,
-			   struct kernel_param *kparam,
+			   const struct kernel_param **kparam,
 			   unsigned int num_params)
 {
 	int err;
kernel/params.c +25 -20

124 lines not on this page · raw message

Signature · 1 line
1.7.3.2
#6 lore raw

Re: [PATCH v2] module: deal with alignment issues in built-in module parameters

Quoted 5 lines · Dmitry Torokhov
Quoted 1 line

From 03f1332fc02af7af0d06ab409e3ec72107637845 Mon Sep 17 00:00:00 2001

From: Dmitry Torokhov <[email protected]>
Date: Mon, 7 Feb 2011 13:47:20 -0800
Subject: [PATCH] module: deal with alignment issues in built-in module parameters

Quoted 7 lines

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.

I've applied this, but won't put it to linux-next. I'll let it stew for a bit longer unless someone actually reports a problem with the current code.

Thanks,
Rusty.

#7 lore raw
In reply to Dmitry Torokhov
Quoted 6 lines · Dmitry Torokhov

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.

Why not?

That's what we normally do. Just align the "__modver", and you should be all good. What's the problem?

Linus

#8 lore raw
Quoted 8 lines · Linus Torvalds
Quoted 6 lines · Dmitry Torokhov

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.

Quoted 4 lines

Why not?

That's what we normally do. Just align the "__modver", and you should be all good. What's the problem?

From what I understand __attribute__ ((aligned(x))) only guarantees minimum alignment, not exact (gapless) alignment. GCC seems to lay out pointers in the section without gaps on all arches that we have.

Thanks.

Signature · 1 line
Dmitry
#9 lore raw
Quoted 4 lines · Dmitry Torokhov

From what I understand __attribute__ ((aligned(x))) only guarantees minimum alignment, not exact (gapless) alignment. GCC seems to lay out pointers in the section without gaps on all arches that we have.

I still don't see the problem.

Have you actually _tried_ just adding the proper alignment to before the __modver thing in include/asm-generic/vmlinux.lds.h ?

As far as I can tell, the bug is really simple:
- the section is not aligned
- but we told the compiler that that structure is aligned

End result: there is a gap between the section start and the first structure.

And the fix seems obvious: just make sure that the section is sufficiently aligned.

IOW, why isn't the proper fix the obvious trivial one (attached)?

Linus

 include/asm-generic/vmlinux.lds.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
include/asm-generic/vmlinux.lds.h +2 -0
index fe77e33..31a4b1d 100644
@@ -358,6 +358,7 @@
 	}								\
 									\
 	/* Built-in module parameters. */				\
+	STRUCT_ALIGN()							\
 	__param : AT(ADDR(__param) - LOAD_OFFSET) {			\
 		VMLINUX_SYMBOL(__start___param) = .;			\
 		*(__param)						\
@@ -365,6 +366,7 @@
 	}								\
 									\
 	/* Built-in module versions. */					\
+	STRUCT_ALIGN()							\
 	__modver : AT(ADDR(__modver) - LOAD_OFFSET) {			\
 		VMLINUX_SYMBOL(__start___modver) = .;			\
 		*(__modver)						\
#10 lore raw
Quoted 15 lines · Linus Torvalds
Quoted 4 lines · Dmitry Torokhov

From what I understand __attribute__ ((aligned(x))) only guarantees minimum alignment, not exact (gapless) alignment. GCC seems to lay out pointers in the section without gaps on all arches that we have.

I still don't see the problem.

Have you actually _tried_ just adding the proper alignment to before the __modver thing in include/asm-generic/vmlinux.lds.h ?

As far as I can tell, the bug is really simple:
- the section is not aligned
- but we told the compiler that that structure is aligned

Quoted 7 lines

End result: there is a gap between the section start and the first structure.

And the fix seems obvious: just make sure that the section is sufficiently aligned.

IOW, why isn't the proper fix the obvious trivial one (attached)?

The problem is that on m68k size of the struct module_version_attribute is not evenly divisible by sizeof(void *), thus when we lay out the __modver section we align on 4 bytes but when we iterate we think that the alignment is 2.

I/Geert tried adding __attribute__ (aligned(sizeof(void *))) to the type definition itself so we have matching alignment everywhere, but DaveM said that this only guarantees minimum alignment and that using structures like we do shown to break from time to time in kprobes and that only pointers worked reliably.

Thanks.

Signature · 1 line
Dmitry
#11 lore raw
Quoted 5 lines · Dmitry Torokhov

The problem is that on m68k size of the struct module_version_attribute is not evenly divisible by sizeof(void *), thus when we lay out the __modver section we align on 4 bytes but when we iterate we think that the alignment is 2.

So mark the struct properly.

Quoted 5 lines

I/Geert tried adding __attribute__ (aligned(sizeof(void *))) to the type definition itself so we have matching alignment everywhere, but DaveM said that this only guarantees minimum alignment and that using structures like we do shown to break from time to time in kprobes and that only pointers worked reliably.

That sounds totally bogus. Minimum alignment is all it needs, and we do that in other places too. I really don't see the reason to add some broken indirection for totally broken reasons. We don't do that with anything else.

David, why are you saying that regular "just mark the structure alignment correctly" doesn't work?

Linus

#12 lore raw

From: Linus Torvalds <[email protected]>
Date: Thu, 17 Feb 2011 10:06:40 -0800

Quoted 2 lines

David, why are you saying that regular "just mark the structure alignment correctly" doesn't work?

Because it's been proven to not work:

http://marc.info/?l=linux-kernel&m=129674396021733&w=2
http://marc.info/?l=linux-kernel&m=129674399621795&w=2
http://marc.info/?l=linux-kernel&m=129674396121739&w=2
http://marc.info/?l=linux-kernel&m=129674396021735&w=2

GCC is very clever with "static" objects these days.

It thinks that, because you mark something "static", it can align it any way it wants because it controls the domain in which the object exists. It "knows" that the object can't be part of an array, and therefore no external entity can be concerned about the true "size" of the object (specifically wrt. side effects of the alignment of the object).

In these cases it takes the explicit alignment attribute as a minimum, not as an absolute requirement.

But we lie to the compiler, we mark things static then put them into a special a special section, then try to iterate over those objects globally as an array and expect the compiler to lay them all out with identical alignments and sizes everywhere.

And this doesn't work.

#13 lore raw
Quoted 2 lines · David Miller

GCC is very clever with "static" objects these days.

I'm sorry, but that simply isn't an acceptable excuse.

The thing is, we DO THIS THING ALL OVER. And the trick used in the original thing (to just turn it into a pointer array instead) _also_ does it. It just happens to do it with a pointer instead of a struct.

So no, I will not take this piece-of-crap patch based on "gcc is trying to be clever, but we can work around it by doing the same thing except now we take the drugs".

That's just stupid.

And I'm scared to see that you have apparently fed those drugs to the perf tree too.

EVERY SINGLE OF YOUR ARGUMENTS WORK FOR "pointer" TOO! It's pure happenstance that gcc doesn't decide to do clever things with them. So replacing that array of structs with array-of-pointers is just voodoo programming.

What is the crap-for-brains thing that gcc actually does, and how can we fix it _properly_ without this kind of voodoo?

Linus

#14 lore raw

From: Linus Torvalds <[email protected]>
Date: Thu, 17 Feb 2011 13:11:56 -0800

Quoted 1 line

EVERY SINGLE OF YOUR ARGUMENTS WORK FOR "pointer" TOO!

It at least will not happen at the current time, because GCC only plays these games on aggregates.

Also, for exception tables, we've avoided this problem because we emit the exception tables by hand using inline asm and therefore explicitly control all aspects of the alignment and size.

The GCC manual even documents the alignment attribute behavior.

Also, please don't shoot the messenger, I didn't make GCC behave this way but I doubt you'll have any luck undoing this behavior in the tools which therefore means as pragmatists we have to handle it one way or another.

#15 lore raw
Quoted 4 lines · David Miller
Quoted 1 line

EVERY SINGLE OF YOUR ARGUMENTS WORK FOR "pointer" TOO!

It at least will not happen at the current time, because GCC only plays these games on aggregates.

So? Do they actually promise to never do it for pointers? What makes aggregates so special? Rather than just happenstance?

I wouldn't be surprised if the structure alignment isn't even about something even subtler and totally random, like size of structure (ie "don't align small structures")

Quoted 3 lines

Also, for exception tables, we've avoided this problem because we emit the exception tables by hand using inline asm and therefore explicitly control all aspects of the alignment and size.

.. and maybe that's the right thing to do here too.

Quoted 1 line

The GCC manual even documents the alignment attribute behavior.

The gcc manual is worthless. Every time some gcc person wants to change behavior, they just change the manual. So you can't rely on it anyway. We've seen that with inline asm before etc.

Quoted 4 lines

Also, please don't shoot the messenger, I didn't make GCC behave this way but I doubt you'll have any luck undoing this behavior in the tools which therefore means as pragmatists we have to handle it one way or another.

I'm shooting not the messenger, but the people who make these kinds of really ugly changes with bad changelogs that don't even explain what the actual problem is. And apparently any gcc person is free to break it in the future _anyway_.

Is there a -fdata-align or something? Or would __attribute__((packed)) help? Something that explicitly tells gcc "don't do this", instead of "let's add indirection and hope gcc doesn't add alignment for _that_". Especially as the extra pointer makes the code even uglier.

And if we do have to use the pointer thing, let's at least then do the pointer with asms, so that gcc _really_ can't screw it up. Rather than just move the potential bug around.

Linus

#16 lore raw

From: Linus Torvalds <[email protected]>
Date: Thu, 17 Feb 2011 13:54:57 -0800

Quoted 4 lines

Is there a -fdata-align or something? Or would __attribute__((packed)) help? Something that explicitly tells gcc "don't do this", instead of "let's add indirection and hope gcc doesn't add alignment for _that_". Especially as the extra pointer makes the code even uglier.

The tracing folks went down the path of trying to use packed in various ways, to no avail, because no matter what they tried it broke other things.

Quoted 3 lines

And if we do have to use the pointer thing, let's at least then do the pointer with asms, so that gcc _really_ can't screw it up. Rather than just move the potential bug around.

That's fine with me.

#17 lore raw
Quoted 12 lines · David Miller

From: Linus Torvalds <[email protected]>
Date: Thu, 17 Feb 2011 13:54:57 -0800

Quoted 4 lines

Is there a -fdata-align or something? Or would __attribute__((packed)) help? Something that explicitly tells gcc "don't do this", instead of "let's add indirection and hope gcc doesn't add alignment for _that_". Especially as the extra pointer makes the code even uglier.

The tracing folks went down the path of trying to use packed in various ways, to no avail, because no matter what they tried it broke other things.

Quoted 5 lines
Quoted 3 lines

And if we do have to use the pointer thing, let's at least then do the pointer with asms, so that gcc _really_ can't screw it up. Rather than just move the potential bug around.

That's fine with me.

Any pointers as to how to emit these pointers with asm?

Signature · 1 line
Dmitry
#18 lore raw

From: Dmitry Torokhov <[email protected]>
Date: Thu, 17 Feb 2011 14:19:57 -0800

Quoted 1 line

Any pointers as to how to emit these pointers with asm?

	.section	FOO_SECTION, "a"
	.align		SIZEOF_POINTER
	.{,x}word	POINTER
	.previous

Where FOO_SECTION is your special section name, SIZEOF_POINTER is sizeof(void *), and POINTER is the pointer you want to add to the section.

You have to also pick .word vs. .xword, or whatever the appropriate sized pointer mnenomic is for a given architecture. I know .word works for 32-bit sparc, and .xword works for 64-bit sparc.

#19 lore raw
Quoted 4 lines · David Miller

You have to also pick .word vs. .xword, or whatever the appropriate sized pointer mnenomic is for a given architecture.  I know .word works for 32-bit sparc, and .xword works for 64-bit sparc.

Gaah, I didn't realize that we've never had to do anything like this before, and that the exception table is all arch-specific code. So we don't have any way to "output that damned pointer and stop whining about it" model at all.

I really detest gcc sometimes. All these "clever" things that just make things harder to do. If the user explicitly tells it the section and the alignment, it should damn well not think that it knows better and change it. Damn.

Maybe we have to take the "just confuse gcc enough and pray" approach on those pointers after all.

Linus

#20 lore raw
Quoted 5 lines · Linus Torvalds

Gaah, I didn't realize that we've never had to do anything like this before, and that the exception table is all arch-specific code. So we don't have any way to "output that damned pointer and stop whining about it" model at all.

Actually, I don't think the problem is about ".word" vs ".xword". We should be able to just use ".long" everywhere.

But the symbol _name_ may have different prefixes, and when we use "asm()" at the top level, we can't use the expressions to fix it up. So a

asm(".long %0":'i" (symbol))

doesn't work (ignore the lack of section naming, that's not important), and neither can we just do something like

  #define output_asm_pointer(section, symbol) \
       asm(".long " #symbol)

portably, because some linker formats want to see prepended underscores etc.

Grr.

Where in gcc is the alignment expansion logic? I'd like to see what the rules are, just for my own perverse satisfaction.

Linus

#21 lore raw

From: Linus Torvalds <[email protected]>
Date: Thu, 17 Feb 2011 15:08:52 -0800

Quoted 2 lines

Where in gcc is the alignment expansion logic? I'd like to see what the rules are, just for my own perverse satisfaction.

The magic that overrides the alignment various cases is in the x86 specific code:

gcc/config/i386/i386.c

ix86_data_alignment() and ix86_local_alignment()

#22 lore raw
In reply to Linus Torvalds
Quoted 17 lines · Linus Torvalds
Quoted 5 lines · Linus Torvalds

Gaah, I didn't realize that we've never had to do anything like this before, and that the exception table is all arch-specific code. So we don't have any way to "output that damned pointer and stop whining about it" model at all.

Actually, I don't think the problem is about ".word" vs ".xword". We should be able to just use ".long" everywhere.

But the symbol _name_ may have different prefixes, and when we use "asm()" at the top level, we can't use the expressions to fix it up. So a

asm(".long %0":'i" (symbol))

Quoted 7 lines

doesn't work (ignore the lack of section naming, that's not important), and neither can we just do something like

  #define output_asm_pointer(section, symbol) \
       asm(".long " #symbol)

portably, because some linker formats want to see prepended underscores etc.

Except that .long is 32-bit on ppc64 :-( You need .llong for 64-bit.

Cheers,
Ben.

#23 lore raw
Quoted 1 line

Except that .long is 32-bit on ppc64 :-( You need .llong for 64-bit.

OK, all options suck. Do we want the workaround or not?

Cheers,
Rusty.

Subject: module: deal with alignment issues in built-in module versions
Date: Mon, 7 Feb 2011 16:02:25 -0800
From: Dmitry Torokhov <[email protected]>

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.

---
 include/linux/module.h |   10 +++++-----
 kernel/params.c        |    9 ++++++---
 2 files changed, 11 insertions(+), 8 deletions(-)
include/linux/module.h +5 -5
index 9bdf27c..9b7081a 100644
@@ -174,10 +174,7 @@ extern struct module __this_module;
 #define MODULE_VERSION(_version)					\
 	extern ssize_t __modver_version_show(struct module_attribute *,	\
 					     struct module *, char *);	\
-	static struct module_version_attribute __modver_version_attr	\
-	__used								\
-    __attribute__ ((__section__ ("__modver"),aligned(sizeof(void *)))) \
-	= {								\
+	static struct module_version_attribute ___modver_attr = {	\
 		.mattr	= {						\
 			.attr	= {					\
 				.name	= "version",			\
@@ -187,7 +184,10 @@ extern struct module __this_module;
 		},							\
 		.module_name	= KBUILD_MODNAME,			\
 		.version	= _version,				\
-	}
+	};								\
+	static const struct module_version_attribute			\
+	__used __attribute__ ((__section__ ("__modver")))		\
+	* __moduleparam_const __modver_attr = &___modver_attr
 #endif
 
 /* Optional firmware file (or files) needed by the module
kernel/params.c +6 -3
index 0da1411..09a08cb 100644
@@ -821,15 +821,18 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
 	return sprintf(buf, "%s\n", vattr->version);
 }
 
-extern struct module_version_attribute __start___modver[], __stop___modver[];
+extern const struct module_version_attribute *__start___modver[];
+extern const struct module_version_attribute *__stop___modver[];
 
 static void __init version_sysfs_builtin(void)
 {
-	const struct module_version_attribute *vattr;
+	const struct module_version_attribute **p;
 	struct module_kobject *mk;
 	int err;
 
-	for (vattr = __start___modver; vattr < __stop___modver; vattr++) {
+	for (p = __start___modver; p < __stop___modver; p++) {
+		const struct module_version_attribute *vattr = *p;
+
 		mk = locate_module_kobject(vattr->module_name);
 		if (mk) {
 			err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
#24 lore raw
Quoted 3 lines · Rusty Russell
Quoted 1 line

Except that .long is 32-bit on ppc64 :-( You need .llong for 64-bit.

OK, all options suck.  Do we want the workaround or not?

We can discuss about that until someone gets bitten by that.

But please fix the "aligned(sizeof(void *))"-in-one-place-only issue.

Quoted 73 lines

Cheers,
Rusty.

Subject: module: deal with alignment issues in built-in module versions
Date: Mon, 7 Feb 2011 16:02:25 -0800
From: Dmitry Torokhov <[email protected]>

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.

---
 include/linux/module.h |   10 +++++-----
 kernel/params.c        |    9 ++++++---

 2 files changed, 11 insertions(+), 8 deletions(-)
include/linux/module.h +5 -5
index 9bdf27c..9b7081a 100644
@@ -174,10 +174,7 @@ extern struct module __this_module;
  #define MODULE_VERSION(_version)                                       \
        extern ssize_t __modver_version_show(struct module_attribute *, \
                                             struct module *, char *);  \
-       static struct module_version_attribute __modver_version_attr    \
-       __used                                                          \
-    __attribute__ ((__section__ ("__modver"),aligned(sizeof(void *)))) \
-       = {                                                             \
+       static struct module_version_attribute ___modver_attr = {       \
                .mattr  = {                                             \
                        .attr   = {                                     \
                                .name   = "version",                    \
@@ -187,7 +184,10 @@ extern struct module __this_module;
                },                                                      \
                .module_name    = KBUILD_MODNAME,                       \
                .version        = _version,                             \
-       }
+       };                                                              \
+       static const struct module_version_attribute                    \
+       __used __attribute__ ((__section__ ("__modver")))               \
+       * __moduleparam_const __modver_attr = &___modver_attr
  #endif
 
  /* Optional firmware file (or files) needed by the module
kernel/params.c +3 -2
index 0da1411..09a08cb 100644
@@ -821,15 +821,18 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
        return sprintf(buf, "%s\n", vattr->version);
  }
 
-extern struct module_version_attribute __start___modver[], __stop___modver[];
+extern const struct module_version_attribute *__start___modver[];
+extern const struct module_version_attribute *__stop___modver[];
 
  static void __init version_sysfs_builtin(void)
  {
-       const struct module_version_attribute *vattr;
+       const struct module_version_attribute **p;

kernel/params.c ssize_t __modver_version_show(struct module_attribute *mattr, · line 838

Quoted 10 lines
kernel/params.c +3 -1
        struct module_kobject *mk;
        int err;
 
-       for (vattr = __start___modver; vattr < __stop___modver; vattr++) {
+       for (p = __start___modver; p < __stop___modver; p++) {
+               const struct module_version_attribute *vattr = *p;
+
                mk = locate_module_kobject(vattr->module_name);
                if (mk) {
                        err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds

#25 lore raw
Quoted 9 lines · Geert Uytterhoeven
Quoted 3 lines · Rusty Russell
Quoted 1 line

Except that .long is 32-bit on ppc64 :-( You need .llong for 64-bit.

OK, all options suck.  Do we want the workaround or not?

We can discuss about that until someone gets bitten by that.

But please fix the "aligned(sizeof(void *))"-in-one-place-only issue.

How about this one then?

Thanks.

Signature · 18 lines
Dmitry

From f0e0e10b58b22047e36e21a022abf5e86b5819c2 Mon Sep 17 00:00:00 2001
From: Dmitry Torokhov <[email protected]>
Date: Fri, 4 Feb 2011 13:30:10 -0800
Subject: [PATCH] module: explicitly align module_version_attribute structure

We force particular alignment when we generate attribute structures
when generation MODULE_VERSION() data and we need to make sure that
this alignment is followed when we iterate over these structures,
otherwise we may crash on platforms whose natural alignment is not
sizeof(void *), such as m68k.

Reported-by: Geert Uytterhoeven <[email protected]>
Signed-off-by: Dmitry Torokhov <[email protected]>
---
 include/linux/module.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/module.h +1 -1
index e7c6385..de5cd21 100644
@@ -62,7 +62,7 @@ struct module_version_attribute {
 	struct module_attribute mattr;
 	const char *module_name;
 	const char *version;
-};
+} __attribute__ ((__aligned__(sizeof(void *))));
 
 struct module_kobject
 {
Signature · 1 line
1.7.3.2
#26 lore raw
Quoted 4 lines · Dmitry Torokhov
Quoted 3 lines · Geert Uytterhoeven
Quoted 2 lines · Rusty Russell
Quoted 1 line

Except that .long is 32-bit on ppc64 :-( You need .llong for 64-bit.

Quoted 8 lines
Quoted 6 lines
Quoted 1 line

OK, all options suck.  Do we want the workaround or not?

We can discuss about that until someone gets bitten by that.

But please fix the "aligned(sizeof(void *))"-in-one-place-only issue.

How about this one then?

Works.

Quoted 5 lines

From f0e0e10b58b22047e36e21a022abf5e86b5819c2 Mon Sep 17 00:00:00 2001
From: Dmitry Torokhov <[email protected]>
Date: Fri, 4 Feb 2011 13:30:10 -0800
Subject: [PATCH] module: explicitly align module_version_attribute structure

Quoted 8 lines

We force particular alignment when we generate attribute structures when generation MODULE_VERSION() data and we need to make sure that this alignment is followed when we iterate over these structures, otherwise we may crash on platforms whose natural alignment is not sizeof(void *), such as m68k.

Quoted 15 lines

---
 include/linux/module.h |    2 +-

 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/module.h +1 -1
index e7c6385..de5cd21 100644
@@ -62,7 +62,7 @@ struct module_version_attribute {
        struct module_attribute mattr;
        const char *module_name;
        const char *version;
-};
+} __attribute__ ((__aligned__(sizeof(void *))));
 
Quoted 4 lines

 struct module_kobject
 {
--
1.7.3.2

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds

#27 lore raw
In reply to Rusty Russell
Quoted 3 lines · Rusty Russell
Quoted 1 line

Except that .long is 32-bit on ppc64 :-( You need .llong for 64-bit.

OK, all options suck. Do we want the workaround or not?

The only sane thing I can see is make sure that such structures that we put into sections "arrays" like that are naturally aligned with padding.

Cheers,
Ben.

Quoted 88 lines

Cheers,
Rusty.

Subject: module: deal with alignment issues in built-in module versions
Date: Mon, 7 Feb 2011 16:02:25 -0800
From: Dmitry Torokhov <[email protected]>

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.

---
 include/linux/module.h |   10 +++++-----
 kernel/params.c        |    9 ++++++---
 2 files changed, 11 insertions(+), 8 deletions(-)
include/linux/module.h +5 -5
index 9bdf27c..9b7081a 100644
@@ -174,10 +174,7 @@ extern struct module __this_module;
 #define MODULE_VERSION(_version)					\
 	extern ssize_t __modver_version_show(struct module_attribute *,	\
 					     struct module *, char *);	\
-	static struct module_version_attribute __modver_version_attr	\
-	__used								\
-    __attribute__ ((__section__ ("__modver"),aligned(sizeof(void *)))) \
-	= {								\
+	static struct module_version_attribute ___modver_attr = {	\
 		.mattr	= {						\
 			.attr	= {					\
 				.name	= "version",			\
@@ -187,7 +184,10 @@ extern struct module __this_module;
 		},							\
 		.module_name	= KBUILD_MODNAME,			\
 		.version	= _version,				\
-	}
+	};								\
+	static const struct module_version_attribute			\
+	__used __attribute__ ((__section__ ("__modver")))		\
+	* __moduleparam_const __modver_attr = &___modver_attr
 #endif
 
 /* Optional firmware file (or files) needed by the module
kernel/params.c +6 -4
index 0da1411..09a08cb 100644
@@ -821,15 +821,18 @@ ssize_t __modver_version_show(struct module_attribute *mattr,
 	return sprintf(buf, "%s\n", vattr->version);
 }
 
-extern struct module_version_attribute __start___modver[], __stop___modver[];
+extern const struct module_version_attribute *__start___modver[];
+extern const struct module_version_attribute *__stop___modver[];
 
 static void __init version_sysfs_builtin(void)
 {
-	const struct module_version_attribute *vattr;
+	const struct module_version_attribute **p;
 	struct module_kobject *mk;
 	int err;
 
-	for (vattr = __start___modver; vattr < __stop___modver; vattr++) {
+	for (p = __start___modver; p < __stop___modver; p++) {
+		const struct module_version_attribute *vattr = *p;
+
 		mk = locate_module_kobject(vattr->module_name);
 		if (mk) {
 			err = sysfs_create_file(&mk->kobj, &vattr->mattr.attr);
--

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#28 lore raw
Quoted 4 lines · Benjamin Herrenschmidt

The only sane thing I can see is make sure that such structures that we put into sections "arrays" like that are naturally aligned with padding.

The sad part is, that assuming I read the gcc sources correctly (see the earlier emails where David pointed to it), that alignment is:
- architecture-specific
- depends on the size of the structure
- seems to depend on the version of gcc itself.

The _one_ safe case is likely to be "structure size is a power of two". And it does look like using a pointer is going to be safe, not only because the gcc auto-alignment only triggers for things like structs/unions/arrays, but because at least the x86 code only does it if the structure was bigger than the alignment size itself.

So using pointer indirection is likely to be safe. It's still ugly and annoying as heck, though.

Linus

#29 lore raw
Quoted 13 lines · Linus Torvalds
Quoted 4 lines · Benjamin Herrenschmidt

The only sane thing I can see is make sure that such structures that we put into sections "arrays" like that are naturally aligned with padding.

The sad part is, that assuming I read the gcc sources correctly (see the earlier emails where David pointed to it), that alignment is:
- architecture-specific
- depends on the size of the structure
- seems to depend on the version of gcc itself.

Quoted 9 lines

The _one_ safe case is likely to be "structure size is a power of two". And it does look like using a pointer is going to be safe, not only because the gcc auto-alignment only triggers for things like structs/unions/arrays, but because at least the x86 code only does it if the structure was bigger than the alignment size itself.

So using pointer indirection is likely to be safe. It's still ugly and annoying as heck, though.

Regardless the approach we'll take I think the following patch is also needed (for cris architecture). I am not sure why __param section is inly defined for one specific subarch but I they need __param they'll need __modev as well.

Thanks,

Dmitry

From a567280f900c15891a55e7ea4e2919b38e1d1a01 Mon Sep 17 00:00:00 2001
From: Dmitry Torokhov <[email protected]>
Date: Thu, 17 Feb 2011 13:12:26 -0800
Subject: [PATCH] cris: add missing __modver section

Commit e94965ed5beb23c6fabf7ed31f625e66d7ff28de added a new __modver section to store module version information for drivers built into the kernel, but missed the fact that cris does some additional steps to set up sections.

---
 arch/cris/kernel/vmlinux.lds.S |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
arch/cris/kernel/vmlinux.lds.S +4 -0
index 4422189..fae1b7b 100644
@@ -73,6 +73,10 @@ SECTIONS
 	.init.data : { INIT_DATA }
 	.init.setup : { INIT_SETUP(16) }
 #ifdef CONFIG_ETRAX_ARCH_V32
+	__start___modver = .;
+	__modver : { *(__modver) }
+	__stop___modver = .;
+
 	__start___param = .;
 	__param : { *(__param) }
 	__stop___param = .;
Signature · 1 line
1.7.3.2
#30 lore raw
Quoted 20 lines · Dmitry Torokhov
Quoted 19 lines · Linus Torvalds
Quoted 4 lines · Benjamin Herrenschmidt

The only sane thing I can see is make sure that such structures that we put into sections "arrays" like that are naturally aligned with padding.

The sad part is, that assuming I read the gcc sources correctly (see the earlier emails where David pointed to it), that alignment is:
- architecture-specific
- depends on the size of the structure
- seems to depend on the version of gcc itself.

The _one_ safe case is likely to be "structure size is a power of two". And it does look like using a pointer is going to be safe, not only because the gcc auto-alignment only triggers for things like structs/unions/arrays, but because at least the x86 code only does it if the structure was bigger than the alignment size itself.

Quoted 7 lines
Quoted 3 lines

So using pointer indirection is likely to be safe. It's still ugly and annoying as heck, though.

Regardless the approach we'll take I think the following patch is also needed (for cris architecture). I am not sure why __param section is inly defined for one specific subarch

That's probably just a legacy from when I combined the linkscripts for the two architectures. If I remember correctly, RODATA brings in RO_DATA_SECTION which in turn brings in __param and __modver for both architectures. CRISv32 then duplicates the __param stuff for some historical reason.

Quoted 2 lines

but I they need __param they'll
need __modev as well.

True, at least until I've made sure that there isn't any underlying reason for CRISv32 to put __param in a different place...

Quoted 3 lines

Thanks,

Dmitry

/Jesper

Quoted 32 lines
Quoted 1 line

From a567280f900c15891a55e7ea4e2919b38e1d1a01 Mon Sep 17 00:00:00 2001

From: Dmitry Torokhov <[email protected]>
Date: Thu, 17 Feb 2011 13:12:26 -0800
Subject: [PATCH] cris: add missing __modver section

Commit e94965ed5beb23c6fabf7ed31f625e66d7ff28de added a new __modver section to store module version information for drivers built into the kernel, but missed the fact that cris does some additional steps to set up sections.

---
 arch/cris/kernel/vmlinux.lds.S |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
arch/cris/kernel/vmlinux.lds.S +4 -0
index 4422189..fae1b7b 100644
@@ -73,6 +73,10 @@ SECTIONS
 	.init.data : { INIT_DATA }
 	.init.setup : { INIT_SETUP(16) }
 #ifdef CONFIG_ETRAX_ARCH_V32
+	__start___modver = .;
+	__modver : { *(__modver) }
+	__stop___modver = .;
+
 	__start___param = .;
 	__param : { *(__param) }
 	__stop___param = .;
Signature · 1 line
1.7.3.2

/^JN - Jesper Nilsson

Signature · 1 line
               Jesper Nilsson -- [email protected]
#31 lore raw
Quoted 6 lines · Jesper Nilsson

That's probably just a legacy from when I combined the linkscripts for the two architectures. If I remember correctly, RODATA brings in RO_DATA_SECTION which in turn brings in __param and __modver for both architectures. CRISv32 then duplicates the __param stuff for some historical reason.

Hmm. This makes it sound like the patch should be to remove the __param thing rather than to add the _modver thing. And I can definitely confirm that cris seems to use RODATA, which brings in the RO_DATA_SECTION() thing with proper page alignment.

But:

Quoted 4 lines

True, at least until I've made sure that there isn't any underlying reason for CRISv32 to put __param in a different place...

I really am not going to apply a patch that likely just adds another redundant field to the linker scripts. So the ack I'm just ignoring,

But it would be good to get the "remove the legacy __param thing because it's already there from the asm-generic version" confirmed by testing, and not just looking at the source code.

Linus

#32 lore raw
Quoted 8 lines · Linus Torvalds
Quoted 4 lines · Jesper Nilsson

True, at least until I've made sure that there isn't any underlying reason for CRISv32 to put __param in a different place...

I really am not going to apply a patch that likely just adds another redundant field to the linker scripts. So the ack I'm just ignoring,

:-)

Quoted 3 lines

But it would be good to get the "remove the legacy __param thing because it's already there from the asm-generic version" confirmed by testing, and not just looking at the source code.

Testing shows no problems with the below patch.

Quoted 1 line

From f8c17a94940a012f237986b4f40ca557a88f9019 Mon Sep 17 00:00:00 2001

From: Jesper Nilsson <[email protected]>
Date: Wed, 23 Feb 2011 13:04:25 +0100
Subject: [PATCH] Drop redundant __param section for CRISv32.

The __param section is already brought in by RODATA above.

---
 arch/cris/kernel/vmlinux.lds.S |    5 -----
 1 files changed, 0 insertions(+), 5 deletions(-)
arch/cris/kernel/vmlinux.lds.S +0 -5
index 917b727..e8adc35 100644
@@ -75,11 +75,6 @@ SECTIONS
 	INIT_TEXT_SECTION(PAGE_SIZE)
 	.init.data : { INIT_DATA }
 	.init.setup : { INIT_SETUP(16) }
-#ifdef CONFIG_ETRAX_ARCH_V32
-	__start___param = .;
-	__param : { *(__param) }
-	__stop___param = .;
-#endif
 	.initcall.init : {
 		INIT_CALLS
 	}
Signature · 1 line
1.7.4
Quoted 1 line

Linus

/^JN - Jesper Nilsson

Signature · 1 line
               Jesper Nilsson -- [email protected]