linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH] firmware: declare __{start,end}_builtin_fw as pointers
@ 2016-06-28 12:23 George Spelvin
  2016-06-28 20:08 ` Linus Torvalds
  0 siblings, 1 reply; 9+ messages in thread
From: George Spelvin @ 2016-06-28 12:23 UTC (permalink / raw)
  To: vegard.nossum; +Cc: linux-kernel

+#define external_array(type, name) \
+	({ \
+		extern type name[]; \
+		type *name_ptr = name; \
+		asm ("" : "+r" (name_ptr)); \
+		name_ptr; \
+	})

I've had to pull similar tricks to persuade GCC to generate
the code I wanted (in my case, it was optimization: "evaluate it
in this order, damn it!"), and I prefer to use the asm itself
with overlapping operands to do the assignment.

#define external_array(type, name) \
	({ \
		extern type name[]; \
		type *name_ptr;
		asm ("" : "=g" (name_ptr) : "0" (name)); \
		name_ptr; \
	})

You could define a wrapper if you like, something like

/*
 * Assign dst = src, but prevent the compiler from inferring anything
 * about the assigned value, so it can't do any unwanted optimization.
 */
#define blind_assign(dst,src) asm("" : "=X" (dst) : "0" (src))

In case it helps, here's a list of architecture-independent operand
constraints (that I think is exhaustive, but I'm not 100% sure):
r - general-purpose register
f - floating-point register
m - memory
o - offsettable memory (excluding pre/post inc/decrement modes)
i - immediate
g - "general", any of the above
X - "wildcard".  This matches anything at all, including special-purpose
    registers that are not included in "r".

^ permalink raw reply	[flat|nested] 9+ messages in thread
* [PATCH] firmware: declare __{start,end}_builtin_fw as pointers
@ 2016-06-25 15:04 Vegard Nossum
  2016-06-25 21:06 ` Vegard Nossum
  0 siblings, 1 reply; 9+ messages in thread
From: Vegard Nossum @ 2016-06-25 15:04 UTC (permalink / raw)
  To: Ming Lei; +Cc: linux-kernel

The test in this loop:

  for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {

was getting completely compiled out by my gcc, 7.0.0 20160520. The result
was that the loop was going beyond the end of the builtin_fw array and
giving me a page fault when trying to dereference b_fw->name inside
strcmp().

I strongly suspect it's because __start_builtin_fw and __end_builtin_fw
are both declared as (separate) arrays, and so gcc conludes that b_fw can
never point to __end_builtin_fw.

By changing these variables from arrays to pointers, gcc can no longer
assume that these are separate arrays.

Cc: stable@vger.kernel.org
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
---
 drivers/base/firmware_class.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 773fc30..4dddf7f 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -43,8 +43,8 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+extern struct builtin_fw *__start_builtin_fw;
+extern struct builtin_fw *__end_builtin_fw;
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name)
 {
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-10-14  6:31 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-28 12:23 [PATCH] firmware: declare __{start,end}_builtin_fw as pointers George Spelvin
2016-06-28 20:08 ` Linus Torvalds
  -- strict thread matches above, loose matches on Subject: below --
2016-06-25 15:04 Vegard Nossum
2016-06-25 21:06 ` Vegard Nossum
2016-06-26  9:24   ` Vegard Nossum
2016-06-26 17:17     ` Linus Torvalds
2016-10-14  5:52       ` Jiri Slaby
2016-10-14  6:25         ` Vegard Nossum
2016-10-14  6:30           ` Jiri Slaby

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).