ARM: avoid Cortex-A9 livelock on tight dmb loops
Subsystems (4)
PATCH v2 1/1 ARM: avoid Cortex-A9 livelock on tight dmb loops
Executing loops such as:
while (1) cpu_relax();
with interrupts disabled results in a livelock of the entire system, as other CPUs are prevented making progress. This is most noticable as a failure of crashdump kexec, which stops just after issuing:
Loading crashdump kernel...
to the system console. Two other locations of these loops within the ARM code have been identified and fixed up.
---
v2: use wfe() instead of cpu_do_idle
arch/arm/include/asm/barrier.h | 2 ++ arch/arm/kernel/machine_kexec.c | 5 ++++- arch/arm/kernel/smp.c | 4 +++- arch/arm/mach-omap2/prm_common.c | 4 +++- 4 files changed, 12 insertions(+), 3 deletions(-)
arch/arm/include/asm/barrier.h +2 -0
@@ -11,6 +11,8 @@#define sev () __asm__ __volatile__ ("sev" : : : "memory")#define wfe () __asm__ __volatile__ ("wfe" : : : "memory")#define wfi () __asm__ __volatile__ ("wfi" : : : "memory") +#else +#define wfe () do { } while (0)#endif #if __LINUX_ARM_ARCH__ >=7
arch/arm/kernel/machine_kexec.c +4 -1
@@ -91,8 +91,11 @@ void machine_crash_nonpanic_core(void *unused)set_cpu_online (smp_processor_id (), false);atomic_dec (&waiting_for_crash_ipi); -while (1 ) + +while (1 ) {cpu_relax (); +wfe (); + } }void crash_smp_send_stop (void )
arch/arm/kernel/smp.c +3 -1
@@ -570,8 +570,10 @@ static void ipi_cpu_stop(unsigned int cpu)local_fiq_disable ();local_irq_disable (); -while (1 ) +while (1 ) {cpu_relax (); +wfe (); + } } static DEFINE_PER_CPU(struct completion *, cpu_completion);
arch/arm/mach-omap2/prm_common.c +3 -1
@@ -522,8 +522,10 @@ void omap_prm_reset_system(void) prm_ll_data->reset_system (); -while (1 ) +while (1 ) {cpu_relax (); +wfe (); + } }/**
Signature · 1 line
2.7.4
Tony Lindgren
maintainerPATCH v2 1/1 ARM: avoid Cortex-A9 livelock on tight dmb loops
Quoted 9 lines · Russell King
Executing loops such as:
while (1) cpu_relax();with interrupts disabled results in a livelock of the entire system, as other CPUs are prevented making progress. This is most noticable as a failure of crashdump kexec, which stops just after issuing:
Quoted 6 lines
Loading crashdump kernel...
to the system console. Two other locations of these loops within the ARM code have been identified and fixed up.
Signed-off-by Russell King <[email protected]>
Works for me thanks:
BTW, do LZMA crashkernels boot for you with crashdump?
For me LZMA crashkernels fail to boot while GZIP crashkernels boots. Some more info below for failing and working output.
Regards,
Tony
8< ----------------------CONFIG_KERNEL_LZMA fails:
Try gzip decompression.
Try LZMA decompression.lzma_decompress_file: read on /boot/zImage of 65536 bytes failed
kernel: 0xb6abb010 kernel_size: 0x43d0f0
MEMORY RANGES
0000000080000000-00000000bfdfffff (0)
zImage header: 0x016f2818 0x00000000 0x0043d0f0
zImage size 0x43d0f0, file size 0x43d0f0
Reserved memory ranges
00000000a8000000-00000000abffffff (0)
Coredump memory ranges
0000000080000000-00000000a7ffffff (0)
00000000ac000000-00000000bfdfffff (0)
kernel symbol _stext vaddr = c0100000
phys offset = 0x80000000, page offset = c0000000
Using 32-bit ELF core formatget_crash_notes_per_cpu: crash_notes addr = be001200, size = 180
Elf header: p_type = 4, p_offset = 0xbe001200 p_paddr = 0xbe001200 p_vaddr = 0x0 p_filesz = 0xb4 p_memsz = 0xb4get_crash_notes_per_cpu: crash_notes addr = be002200, size = 180
Elf header: p_type = 4, p_offset = 0xbe002200 p_paddr = 0xbe002200 p_vaddr = 0x0 p_filesz = 0xb4 p_memsz = 0xb4 vmcoreinfo header: p_type = 4, p_offset = 0xaeae2000 p_paddr = 0xaeae2000 p_vaddr = 0x0 p_filesz = 0x1024 p_memsz = 0x1024 Elf header: p_type = 1, p_offset = 0x80000000 p_paddr = 0x80000000 p_vaddr = 0xc0000000 p_filesz = 0x28000000 p_memsz = 0x2800 0000
Elf header: p_type = 1, p_offset = 0xac000000 p_paddr = 0xac000000 p_vaddr = 0xec000000 p_filesz = 0x13e00000 p_memsz = 0x13e0 0000
elfcorehdr: 0xabf00000
crashkernel: [0xa8000000 - 0xabffffff] (64M)
memory range: [0x80000000 - 0xa7ffffff] (640M)
memory range: [0xac000000 - 0xbfdfffff] (318M)
kernel command line: "console=ttyS2,115200n8 root=/dev/nfs ip=dhcp debug earlyprintk earlycon crashkernel=64M elfcorehdr=0xabf 00000 mem=64512K"kexec_load: entry = 0xa8008000 flags = 0x280001nr_segments = 3
segment[0].buf = 0xb6abb010
segment[0].bufsz = 0x43d0f0
segment[0].mem = 0xa8008000
segment[0].memsz = 0x43e000
segment[1].buf = 0x53dc80
segment[1].bufsz = 0x128da
segment[1].mem = 0xa953b000
segment[1].memsz = 0x13000
segment[2].buf = 0xb6fe8150
segment[2].bufsz = 0x400
segment[2].mem = 0xabf00000
segment[2].memsz = 0x1000
CONFIG_KERNEL_GZIP Works:
Try gzip decompression.
Try LZMA decompression.lzma_decompress_file: read on /boot/zImage of 65536 bytes failed
kernel: 0xb693f010 kernel_size: 0x5c74a8
MEMORY RANGES
0000000080000000-00000000bfdfffff (0)
zImage header: 0x016f2818 0x00000000 0x005c74a8
zImage size 0x5c74a8, file size 0x5c74a8
Reserved memory ranges
00000000a8000000-00000000abffffff (0)
Coredump memory ranges
0000000080000000-00000000a7ffffff (0)
00000000ac000000-00000000bfdfffff (0)
kernel symbol _stext vaddr = c0100000
phys offset = 0x80000000, page offset = c0000000
Using 32-bit ELF core formatget_crash_notes_per_cpu: crash_notes addr = be001200, size = 180
Elf header: p_type = 4, p_offset = 0xbe001200 p_paddr = 0xbe001200 p_vaddr = 0x0 p_filesz = 0xb4 p_memsz = 0xb4get_crash_notes_per_cpu: crash_notes addr = be002200, size = 180
Elf header: p_type = 4, p_offset = 0xbe002200 p_paddr = 0xbe002200 p_vaddr = 0x0 p_filesz = 0xb4 p_memsz = 0xb4 vmcoreinfo header: p_type = 4, p_offset = 0xaeae2000 p_paddr = 0xaeae2000 p_vaddr = 0x0 p_filesz = 0x1024 p_memsz = 0x1024 Elf header: p_type = 1, p_offset = 0x80000000 p_paddr = 0x80000000 p_vaddr = 0xc0000000 p_filesz = 0x28000000 p_memsz = 0x28000000 Elf header: p_type = 1, p_offset = 0xac000000 p_paddr = 0xac000000 p_vaddr = 0xec000000 p_filesz = 0x13e00000 p_memsz = 0x13e00000
elfcorehdr: 0xabf00000
crashkernel: [0xa8000000 - 0xabffffff] (64M)
memory range: [0x80000000 - 0xa7ffffff] (640M)
memory range: [0xac000000 - 0xbfdfffff] (318M)
kernel command line: "console=ttyS2,115200n8 root=/dev/nfs ip=dhcp debug earlyprintk earlycon crashkernel=64M elfcorehdr=0xabf00000 mem=64512K"kexec_load: entry = 0xa8008000 flags = 0x280001nr_segments = 3
segment[0].buf = 0xb693f010
segment[0].bufsz = 0x5c74a8
segment[0].mem = 0xa8008000
segment[0].memsz = 0x5c8000
segment[1].buf = 0x476c80
segment[1].bufsz = 0x128da
segment[1].mem = 0xa9cee000
segment[1].memsz = 0x13000
segment[2].buf = 0xb6ff6150
segment[2].bufsz = 0x400
segment[2].mem = 0xabf00000
segment[2].memsz = 0x1000
Russell King - ARM Linux
maintainerPATCH v2 1/1 ARM: avoid Cortex-A9 livelock on tight dmb loops
Quoted 12 lines · Tony Lindgren
Quoted 11 lines · Russell King
Executing loops such as:
while (1) cpu_relax();with interrupts disabled results in a livelock of the entire system, as other CPUs are prevented making progress. This is most noticable as a failure of crashdump kexec, which stops just after issuing:
Loading crashdump kernel...
Quoted 8 lines
Quoted 4 lines
to the system console. Two other locations of these loops within the ARM code have been identified and fixed up.
Signed-off-by Russell King <[email protected]>Works for me thanks:
Tested-by Tony Lindgren <[email protected]>
Thanks.
Quoted 12 lines
BTW, do LZMA crashkernels boot for you with crashdump?
For me LZMA crashkernels fail to boot while GZIP crashkernels boots. Some more info below for failing and working output.
Regards,
Tony
8< ----------------------
CONFIG_KERNEL_LZMAfails:
Quoted 9 lines
Try gzip decompression.
Try LZMA decompression.lzma_decompress_file: read on/boot/zImageof 65536 bytes failed
kernel:0xb6abb010kernel_size:0x43d0f0
MEMORY RANGES
0000000080000000-00000000bfdfffff (0)
zImage header:0x016f28180x000000000x0043d0f0
zImage size0x43d0f0, file size0x43d0f0
Reserved memory ranges
This looks like an old kexec binary as it's missing the output from:
dbgprintf("zImage requires 0x%08llx bytes\n", (unsigned long long)len);Please can you test with the current version - the official repository should now be up to date with my version. Thanks.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up
Tony Lindgren
maintainerPATCH v2 1/1 ARM: avoid Cortex-A9 livelock on tight dmb loops
Quoted 13 lines · Russell King - ARM Linux
Quoted 11 lines · Tony Lindgren
CONFIG_KERNEL_LZMAfails:Try gzip decompression.
Try LZMA decompression.lzma_decompress_file: read on/boot/zImageof 65536 bytes failed
kernel:0xb6abb010kernel_size:0x43d0f0
MEMORY RANGES
0000000080000000-00000000bfdfffff (0)
zImage header:0x016f28180x000000000x0043d0f0
zImage size0x43d0f0, file size0x43d0f0
Reserved memory ranges
Quoted 6 lines
This looks like an old kexec binary as it's missing the output from:
dbgprintf("zImage requires 0x%08llx bytes\n", (unsigned long long)len);Please can you test with the current version - the official repository should now be up to date with my version. Thanks.
OK great. After updating kexec-tools to latest git veresion LZMA crashkernel now also boots for me :)
Regards,
Tony
PATCH v2 1/1 ARM: avoid Cortex-A9 livelock on tight dmb loops
In reply to Russell KingHi Russell,
Quoted 5 lines · Russell King
Executing loops such as:
while (1) cpu_relax();
Quoted 8 lines
with interrupts disabled results in a livelock of the entire system, as other CPUs are prevented making progress. This is most noticable as a failure of crashdump kexec, which stops just after issuing:
Loading crashdump kernel...
to the system console. Two other locations of these loops within the ARM code have been identified and fixed up.
Can you confirm that this only happens if CONFIG_ARM_ERRATA_754327=y? The only erratum I can find for A9 that matches this behaviour exists when the body of the tight loop contains a DMB and some of the possible workarounds are:
- Add ten NOPs after the DMB
- Use DSB instead of DMB in the tight loop
- Set bit 16 in the diagnostic control register (p15, c1, 5, 0, c0, 1)
WFE is probably fine (the write-up isn't clear), but if this only occurs due to CONFIG_ARM_ERRATA_754327=y it would be nice to mitigate it in the alternative cpu_relax() definition itself, which isn't generally possible with WFE.
Will
Russell King - ARM Linux
maintainerPATCH v2 1/1 ARM: avoid Cortex-A9 livelock on tight dmb loops
Quoted 12 lines · Will Deacon
Hi Russell,
Quoted 9 lines · Russell King
Executing loops such as:
while (1) cpu_relax();with interrupts disabled results in a livelock of the entire system, as other CPUs are prevented making progress. This is most noticable as a failure of crashdump kexec, which stops just after issuing:
Quoted 6 lines
Quoted 4 lines
Loading crashdump kernel...
to the system console. Two other locations of these loops within the ARM code have been identified and fixed up.
Can you confirm that this only happens if
CONFIG_ARM_ERRATA_754327=y?
CONFIG_ARM_ERRATA_754327=y + patch => worksCONFIG_ARM_ERRATA_754327=y => failsCONFIG_ARM_ERRATA_754327=n => works
Quoted 7 lines
The only erratum I can find for A9 that matches this behaviour exists when the body of the tight loop contains a DMB and some of the possible workarounds are:
- Add ten NOPs after the DMB
- Use DSB instead of DMB in the tight loop
- Set bit 16 in the diagnostic control register (p15, c1, 5, 0, c0, 1)
Yes, I think you pointed me at that. It may be appropriate to mitigate the cases where we have a tight loop where the loop has a termination condition, but in these cases, all the loops are infinite - finding some way to avoid spinning in this case is probably a good idea in any case.
What I'm more interested in this patch is to fix kexec crashdump when CONFIG_ARM_ERRATA_754327=y on OMAP4 (and similar) platforms.
Quoted 4 lines
WFE is probably fine (the write-up isn't clear), but if this only occurs due to
CONFIG_ARM_ERRATA_754327=yit would be nice to mitigate it in the alternativecpu_relax()definition itself, which isn't generally possible with WFE.
With the WFE, it is no longer "a tight loop", although WFE is just a hint to the processor, it could ultimately ignore it. That said, in all these cases, either:
- we're either talking about a secondary CPU, so SMP must be supported (which presumably guarantees implementation of SEV/WFE)
or:
- we're the only CPU so this problem doesn't apply to the infinite loop case.
Signature · 3 lines
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up According to speedtest.net: 8.21Mbps down 510kbps up