* Missing volatile in hard_smp_processor_id.
@ 2011-06-27 23:03 Gilles Chanteperdrix
2011-06-27 23:16 ` Russell King - ARM Linux
0 siblings, 1 reply; 2+ messages in thread
From: Gilles Chanteperdrix @ 2011-06-27 23:03 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
all the versions of codesourcery from 2009q1 to 2010.09 optimize too
eagerly the calls to hard_smp_processor_id.
The following code:
#define hard_smp_processor_id() \
({ \
unsigned int cpunum; \
__asm__("\n" \
"1: mrc p15, 0, %0, c0, c0, 5\n" \
" .pushsection \".alt.smp.init\", \"a\"\n"\
" .long 1b\n" \
" mov %0, #0\n" \
" .popsection" \
: "=r" (cpunum)); \
cpunum &= 0x0F; \
})
static inline unsigned long arch_local_irq_save(void)
{
unsigned long flags;
asm volatile(
" mrs %0, cpsr @ arch_local_irq_save\n"
" cpsid i"
: "=r" (flags) : : "memory", "cc");
return flags;
}
static inline void arch_local_irq_restore(unsigned long flags)
{
asm volatile(
" msr cpsr_c, %0 @ local_irq_restore"
:
: "r" (flags)
: "memory", "cc");
}
struct thread_info {
unsigned long flags; /* low level flags */
int preempt_count; /* 0 => preemptable, <0 => bug */
unsigned cpu; /* cpu */
};
static inline struct thread_info *current_thread_info(void) __attribute__((const));
static inline struct thread_info *current_thread_info(void)
{
register unsigned long sp asm ("sp");
return (struct thread_info *)(sp & ~8191);
}
extern int printk(const char *fmt, ...);
void f(void)
{
unsigned long flags;
unsigned cpu0, cpu1;
flags = arch_local_irq_save();
cpu0 = hard_smp_processor_id();
cpu1 = current_thread_info()->cpu;
arch_local_irq_restore(flags);
printk("cpu %d, %d\n", cpu0, cpu1);
flags = arch_local_irq_save();
cpu0 = hard_smp_processor_id();
cpu1 = current_thread_info()->cpu;
arch_local_irq_restore(flags);
printk("cpu %d\n", cpu0, cpu1);
}
gives:
00000024 <f>:
24: e92d41f0 push {r4, r5, r6, r7, r8, lr}
28: ebfffff4 bl 0 <arch_local_irq_save>
2c: ee104fb0 mrc 15, 0, r4, cr0, cr0, {5}
30: e204400f and r4, r4, #15
34: e1a07000 mov r7, r0
38: ebfffff5 bl 14 <current_thread_info>
3c: e5906008 ldr r6, [r0, #8]
40: e1a05000 mov r5, r0
44: e1a00007 mov r0, r7
48: ebffffef bl c <arch_local_irq_restore>
4c: e1a01004 mov r1, r4
50: e1a02006 mov r2, r6
54: e59f0020 ldr r0, [pc, #32] ; 7c <f+0x58>
58: ebfffffe bl 0 <printk>
5c: ebffffe7 bl 0 <arch_local_irq_save>
60: e5955008 ldr r5, [r5, #8]
64: ebffffe8 bl c <arch_local_irq_restore>
68: e59f0010 ldr r0, [pc, #16] ; 80 <f+0x5c>
6c: e1a01004 mov r1, r4
70: e1a02005 mov r2, r5
74: e8bd41f0 pop {r4, r5, r6, r7, r8, lr}
78: eafffffe b 0 <printk>
7c: 00000000 .word 0x00000000
80: 0000000c .word 0x0000000c
Where we see that the cpu number is read only once from cp15. This
is problematic, as a task may migrate as soon as irqs are on.
Adding a "volatile" to the inline assembly in hard_smp_processor_id()
fixes it.
I know hard_smp_processor_id() disappeared after Linux 2.6.37, but this
may be interesting for the stable and long term support branches. This
issue is suspected to cause random segmentation faults on OMAP4 with
CONFIG_HIGHMEM on.
Regards.
--
Gilles.
^ permalink raw reply [flat|nested] 2+ messages in thread* Missing volatile in hard_smp_processor_id.
2011-06-27 23:03 Missing volatile in hard_smp_processor_id Gilles Chanteperdrix
@ 2011-06-27 23:16 ` Russell King - ARM Linux
0 siblings, 0 replies; 2+ messages in thread
From: Russell King - ARM Linux @ 2011-06-27 23:16 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jun 28, 2011 at 01:03:41AM +0200, Gilles Chanteperdrix wrote:
> I know hard_smp_processor_id() disappeared after Linux 2.6.37, but this
> may be interesting for the stable and long term support branches. This
> issue is suspected to cause random segmentation faults on OMAP4 with
> CONFIG_HIGHMEM on.
1. hard_smp_processor_id() was only used in the platform hotplug code
to verify that the intended CPU number was the same as the hardware
CPU number. These checks were removed by bbc81fd (ARM: CPU hotplug:
remove bug checks in platform_cpu_die()).
2. OMAP - and as a general principle, no one else - does not and should
not make use of this macro. CPU numbers within Linux are 'logical' and
may not correspond with the hardware CPU number. However, there are
three places where we make the assumption that they're the same:
a) CPU bringup code
b) GIC cross-call code
c) Hotplug code
Even these places make no reference to the MPIDR register - the only
place which does is the very early assembly code.
_Anything_ which uses hard_smp_processor_id() is probably buggy. We have
get_cpu()..put_cpu() to deal with preemption etc, and in any case the
logical CPU number should always be used for indexing data structures.
Finally, there is no code merged into mainline which mis-uses this
macro.
So, all in all I see no reason to submit patches to stable trees for
something which doesn't cause a problem in those trees themselves.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2011-06-27 23:16 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-27 23:03 Missing volatile in hard_smp_processor_id Gilles Chanteperdrix
2011-06-27 23:16 ` Russell King - ARM Linux
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox