public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* s390(64) per_cpu in modules (ipv6)
@ 2004-06-30  6:35 Pete Zaitcev
  2004-06-30  6:45 ` William Lee Irwin III
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Pete Zaitcev @ 2004-06-30  6:35 UTC (permalink / raw)
  To: schwidefsky; +Cc: zaitcev, linux-kernel

Hi, Martin,

I tried to build ipv6 as a module in 2.6.7, and it bombs, producing a
module which wants per_cpu____icmpv6_socket (obviously, undefined).

The problem appears to be caused by this:

#define __get_got_cpu_var(var,offset) \
  (*({ unsigned long *__ptr; \
       asm ( "larl %0,per_cpu__"#var"@GOTENT" : "=a" (__ptr) ); \
       ((typeof(&per_cpu__##var))((*__ptr) + offset)); \
    }))

The net/ipv6/icmp.c has this:

static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL;

It is a static variable, and all references to it come from asm code.
The gcc does not know that they are present and optimizes the variable
away. It simply emits no code to define per_cpu____icmpv6_socket
whatsoever, as verified with gcc -S.

If the DEFINE_PER_CPU() is used without static, or if a bogus
reference is added to the C code (a printk), everything works.

I tried to add a fake input argument to the asm, like this:

--- linux-2.6.7-1.459/include/asm-s390/percpu.h 2004-06-16 01:20:04.000000000 -0400
+++ linux-2.6.7-1.459.z1/include/asm-s390/percpu.h      2004-06-29 22:03:23.000000000 -0400
@@ -15,7 +15,7 @@
 #if defined(__s390x__) && defined(MODULE)
 #define __get_got_cpu_var(var,offset) \
   (*({ unsigned long *__ptr; \
-       asm ( "larl %0,per_cpu__"#var"@GOTENT" : "=a" (__ptr) ); \
+       asm ( "larl %0,per_cpu__"#var"@GOTENT" : "=a" (__ptr) : "a" (&per_cpu__##var) ); \
        ((typeof(&per_cpu__##var))((*__ptr) + offset)); \
     }))
 #undef __get_cpu_var

It seems to work fine, but I'm wondering if a better fix can be found.
Ideas?

-- Pete

^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: s390(64) per_cpu in modules (ipv6)
@ 2004-06-30 13:04 Martin Schwidefsky
  2004-06-30 16:07 ` Roland Dreier
  2004-06-30 20:55 ` Pete Zaitcev
  0 siblings, 2 replies; 9+ messages in thread
From: Martin Schwidefsky @ 2004-06-30 13:04 UTC (permalink / raw)
  To: William Lee Irwin III; +Cc: Pete Zaitcev, linux-kernel

> > It seems to work fine, but I'm wondering if a better fix can
> > be found.
> 
> How does __attribute__((used)) fare?

__attribute_used__ isn't really what we want. If a statically
defined per cpu variable isn't used in the C file then gcc
should be allowed to remove it. It's not used after all.
What we need is a way to tell the compiler that an inline
assembly uses a variable without passing any kind of address
of the variable to it. The solution is the "X" constraint.
While I was at it I cleaned things up a bit, I don't like
the #undefs in percpu.h. Patch is attached, I will include
it in my next update for Andrew.

blue skies,
  Martin.

diff -urN linux-2.6/include/asm-s390/percpu.h linux-2.6-s390/include/asm-s390/percpu.h
--- linux-2.6/include/asm-s390/percpu.h	Wed Jun 16 07:20:04 2004
+++ linux-2.6-s390/include/asm-s390/percpu.h	Wed Jun 30 14:37:45 2004
@@ -1,30 +1,70 @@
 #ifndef __ARCH_S390_PERCPU__
 #define __ARCH_S390_PERCPU__
 
-#include <asm-generic/percpu.h>
+#include <linux/compiler.h>
 #include <asm/lowcore.h>
 
+#define __GENERIC_PER_CPU
+
 /*
- * For builtin kernel code s390 uses the generic implementation for
- * per cpu data, with the exception that the offset of the cpu local
- * data area is cached in the cpu's lowcore memory
+ * s390 uses its own implementation for per cpu data, the offset of
+ * the cpu local data area is cached in the cpu's lowcore memory.
  * For 64 bit module code s390 forces the use of a GOT slot for the
  * address of the per cpu variable. This is needed because the module
  * may be more than 4G above the per cpu area.
  */
 #if defined(__s390x__) && defined(MODULE)
-#define __get_got_cpu_var(var,offset) \
+
+#define __reloc_hide(var,offset) \
   (*({ unsigned long *__ptr; \
-       asm ( "larl %0,per_cpu__"#var"@GOTENT" : "=a" (__ptr) ); \
-       ((typeof(&per_cpu__##var))((*__ptr) + offset)); \
-    }))
-#undef __get_cpu_var
-#define __get_cpu_var(var) __get_got_cpu_var(var,S390_lowcore.percpu_offset)
-#undef per_cpu
-#define per_cpu(var,cpu) __get_got_cpu_var(var,__per_cpu_offset[cpu])
+       asm ( "larl %0,per_cpu__"#var"@GOTENT" \
+             : "=a" (__ptr) : "X" (per_cpu__##var) ); \
+       (typeof(&per_cpu__##var))((*__ptr) + (offset)); }))
+
 #else
-#undef __get_cpu_var
-#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, S390_lowcore.percpu_offset))
+
+#define __reloc_hide(var, offset) \
+  (*({ unsigned long __ptr; \
+       asm ( "" : "=a" (__ptr) : "0" (&per_cpu__##var) ); \
+       (typeof(&per_cpu__##var)) (__ptr + (offset)); }))
+
 #endif
 
+#ifdef CONFIG_SMP
+
+extern unsigned long __per_cpu_offset[NR_CPUS];
+
+/* Separate out the type, so (int[3], foo) works. */
+#define DEFINE_PER_CPU(type, name) \
+    __attribute__((__section__(".data.percpu"))) \
+    __typeof__(type) per_cpu__##name
+
+#define __get_cpu_var(var) __reloc_hide(var,S390_lowcore.percpu_offset)
+#define per_cpu(var,cpu) __reloc_hide(var,__per_cpu_offset[cpu])
+
+/* A macro to avoid #include hell... */
+#define percpu_modcopy(pcpudst, src, size)			\
+do {								\
+	unsigned int __i;					\
+	for (__i = 0; __i < NR_CPUS; __i++)			\
+		if (cpu_possible(__i))				\
+			memcpy((pcpudst)+__per_cpu_offset[__i],	\
+			       (src), (size));			\
+} while (0)
+
+#else /* ! SMP */
+
+#define DEFINE_PER_CPU(type, name) \
+    __typeof__(type) per_cpu__##name
+
+#define __get_cpu_var(var) __reloc_hide(var,0)
+#define per_cpu(var,cpu) __reloc_hide(var,0)
+
+#endif /* SMP */
+
+#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
+
+#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
+#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
+
 #endif /* __ARCH_S390_PERCPU__ */

^ permalink raw reply	[flat|nested] 9+ messages in thread
[parent not found: <OFC25D1557.60BFB654-ON42256F2E.00327ABF-42256F2E.0032D239@de.ibm.com>]

end of thread, other threads:[~2004-10-17  2:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-06-30  6:35 s390(64) per_cpu in modules (ipv6) Pete Zaitcev
2004-06-30  6:45 ` William Lee Irwin III
2004-06-30  6:46 ` Roland Dreier
2004-10-15  1:41 ` Rusty Russell
  -- strict thread matches above, loose matches on Subject: below --
2004-06-30 13:04 Martin Schwidefsky
2004-06-30 16:07 ` Roland Dreier
2004-06-30 20:55 ` Pete Zaitcev
2004-07-01 13:05   ` Arnd Bergmann
     [not found] <OFC25D1557.60BFB654-ON42256F2E.00327ABF-42256F2E.0032D239@de.ibm.com>
2004-10-17  2:51 ` Rusty Russell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox