From: Arnd Bergmann I got a bug report about loading some modules on s390 (for the privileged, see http://bugzilla.suse.de/show_bug.cgi?id=38820). The problem is that modules are loaded to a virtual address that is far away (roughly main memory size) from the percpu kernel section, but s390x-gcc generates only 32-bit relocations for static variables. My suspicion is that there are some more architectures where a relocation for static variables is not sufficient for per-cpu data. Can anyone confirm this? Fortunately, this currently occurs only in scsi.ko and ipv6.ko even for allmodconfig, so these are trivial to work around by changing the scope of the percpu variables. The idea I had for preventing the same bug from happening in the future is to provoke a compile error for modules using 'static DEFINE_PER_CPU', see patch below. Alternatively, we could introduce a 'STATIC_DEFINE_PER_CPU' that replaces 'static DEFINE_PER_CPU' for non-module builds, or redefine 'DEFINE_PER_CPU' in include/asm-s390 in a way that the 'static' get silently ignored for modules. --- 25-akpm/drivers/scsi/scsi.c | 2 +- 25-akpm/include/asm-generic/percpu.h | 12 ++++++++++++ 25-akpm/net/ipv6/icmp.c | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff -puN drivers/scsi/scsi.c~static-define_per_cpu-vs-modules-2 drivers/scsi/scsi.c --- 25/drivers/scsi/scsi.c~static-define_per_cpu-vs-modules-2 2004-05-04 12:04:32.074201928 -0700 +++ 25-akpm/drivers/scsi/scsi.c 2004-05-04 12:04:32.098198280 -0700 @@ -672,7 +672,7 @@ void scsi_init_cmd_from_req(struct scsi_ /* * Per-CPU I/O completion queue. */ -static DEFINE_PER_CPU(struct list_head, scsi_done_q); +DEFINE_PER_CPU(struct list_head, scsi_done_q); /** * scsi_done - Enqueue the finished SCSI command into the done queue. diff -puN include/asm-generic/percpu.h~static-define_per_cpu-vs-modules-2 include/asm-generic/percpu.h --- 25/include/asm-generic/percpu.h~static-define_per_cpu-vs-modules-2 2004-05-04 12:04:32.083200560 -0700 +++ 25-akpm/include/asm-generic/percpu.h 2004-05-04 12:04:32.098198280 -0700 @@ -3,12 +3,23 @@ #include #define __GENERIC_PER_CPU + +/* modules must not use "static DEFINE_PER_CPU", so add an + * extern declaration that causes a compile error if somebody + * attempts */ +#ifndef MODULE +#define __PER_CPU_NOSTATIC(decl) +#else +#define __PER_CPU_NOSTATIC(decl) extern decl; +#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) \ + __PER_CPU_NOSTATIC(__typeof__(type) per_cpu__##name) \ __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name /* var is in discarded region: offset to particular copy we want */ @@ -27,6 +38,7 @@ do { \ #else /* ! SMP */ #define DEFINE_PER_CPU(type, name) \ + __PER_CPU_NOSTATIC(__typeof__(type) per_cpu__##name) \ __typeof__(type) per_cpu__##name #define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var)) diff -puN net/ipv6/icmp.c~static-define_per_cpu-vs-modules-2 net/ipv6/icmp.c --- 25/net/ipv6/icmp.c~static-define_per_cpu-vs-modules-2 2004-05-04 12:04:32.094198888 -0700 +++ 25-akpm/net/ipv6/icmp.c 2004-05-04 12:04:32.099198128 -0700 @@ -76,7 +76,7 @@ DEFINE_SNMP_STAT(struct icmpv6_mib, icmp * * On SMP we have one ICMP socket per-cpu. */ -static DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; +DEFINE_PER_CPU(struct socket *, __icmpv6_socket) = NULL; #define icmpv6_socket __get_cpu_var(__icmpv6_socket) static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp); _