* [PATCH 1/3] powerpc/xmon: Don't loop forever in get_output_lock()
@ 2013-12-23 12:46 Michael Ellerman
2013-12-23 12:46 ` [PATCH 2/3] powerpc/xmon: Fix timeout loop " Michael Ellerman
2013-12-23 12:46 ` [PATCH 3/3] powerpc/xmon: Don't signal we've entered until we're finished printing Michael Ellerman
0 siblings, 2 replies; 3+ messages in thread
From: Michael Ellerman @ 2013-12-23 12:46 UTC (permalink / raw)
To: linuxppc-dev
From: Michael Ellerman <michael@ellerman.id.au>
If we enter with xmon_speaker != 0 we skip the first cmpxchg(), we also
skip the while loop because xmon_speaker != last_speaker (0) - meaning we
skip the second cmpxchg() also.
Following that code path the compiler sees no memory barriers and so is
within its rights to never reload xmon_speaker. The end result is we loop
forever.
This manifests as all cpus being in xmon ('c' command), but they refuse
to take control when you switch to them ('c x' for cpu # x).
I have seen this deadlock in practice and also checked the generated code to
confirm this is what's happening.
The simplest fix is just to always try the cmpxchg().
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/xmon/xmon.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index af9d346..500105c 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -309,12 +309,12 @@ static void get_output_lock(void)
if (xmon_speaker == me)
return;
+
for (;;) {
- if (xmon_speaker == 0) {
- last_speaker = cmpxchg(&xmon_speaker, 0, me);
- if (last_speaker == 0)
- return;
- }
+ last_speaker = cmpxchg(&xmon_speaker, 0, me);
+ if (last_speaker == 0)
+ return;
+
timeout = 10000000;
while (xmon_speaker == last_speaker) {
if (--timeout > 0)
--
1.8.3.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/3] powerpc/xmon: Fix timeout loop in get_output_lock()
2013-12-23 12:46 [PATCH 1/3] powerpc/xmon: Don't loop forever in get_output_lock() Michael Ellerman
@ 2013-12-23 12:46 ` Michael Ellerman
2013-12-23 12:46 ` [PATCH 3/3] powerpc/xmon: Don't signal we've entered until we're finished printing Michael Ellerman
1 sibling, 0 replies; 3+ messages in thread
From: Michael Ellerman @ 2013-12-23 12:46 UTC (permalink / raw)
To: linuxppc-dev
As far as I can tell, our 70s era timeout loop in get_output_lock() is
generating no code.
This leads to the hostile takeover happening more or less simultaneously
on all cpus. The result is "interesting", some example output that is
more readable than most:
cpu 0x1: Vector: 100 (Scypsut e0mx bR:e setV)e catto xc0p:u[ c 00
c0:0 000t0o0V0erc0td:o5 rfc28050000]0c00 0 0 0 6t(pSrycsV1ppuot
uxe 1m 2 0Rx21e3:0s0ce000c00000t00)00 60602oV2SerucSayt0y 0p 1sxs
Fix it by using udelay() in the timeout loop. The wait time and check
frequency are arbitrary, but seem to work OK. We already rely on
udelay() working so this is not a new dependency.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/xmon/xmon.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 500105c..051037e 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -315,10 +315,17 @@ static void get_output_lock(void)
if (last_speaker == 0)
return;
- timeout = 10000000;
+ /*
+ * Wait a full second for the lock, we might be on a slow
+ * console, but check every 100us.
+ */
+ timeout = 10000;
while (xmon_speaker == last_speaker) {
- if (--timeout > 0)
+ if (--timeout > 0) {
+ udelay(100);
continue;
+ }
+
/* hostile takeover */
prev = cmpxchg(&xmon_speaker, last_speaker, me);
if (prev == last_speaker)
--
1.8.3.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 3/3] powerpc/xmon: Don't signal we've entered until we're finished printing
2013-12-23 12:46 [PATCH 1/3] powerpc/xmon: Don't loop forever in get_output_lock() Michael Ellerman
2013-12-23 12:46 ` [PATCH 2/3] powerpc/xmon: Fix timeout loop " Michael Ellerman
@ 2013-12-23 12:46 ` Michael Ellerman
1 sibling, 0 replies; 3+ messages in thread
From: Michael Ellerman @ 2013-12-23 12:46 UTC (permalink / raw)
To: linuxppc-dev
Currently we set our cpu's bit in cpus_in_xmon, and then we take the
output lock and print the exception information.
This can race with the master cpu entering the command loop and printing
the backtrace. The result is that the backtrace gets garbled with
another cpu's exception print out.
Fix it by delaying the set of cpus_in_xmon until we are finished
printing.
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/xmon/xmon.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 051037e..b59f44f 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -404,7 +404,6 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
}
xmon_fault_jmp[cpu] = recurse_jmp;
- cpumask_set_cpu(cpu, &cpus_in_xmon);
bp = NULL;
if ((regs->msr & (MSR_IR|MSR_PR|MSR_64BIT)) == (MSR_IR|MSR_64BIT))
@@ -426,6 +425,8 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
release_output_lock();
}
+ cpumask_set_cpu(cpu, &cpus_in_xmon);
+
waiting:
secondary = 1;
while (secondary && !xmon_gate) {
--
1.8.3.2
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2013-12-23 12:46 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-23 12:46 [PATCH 1/3] powerpc/xmon: Don't loop forever in get_output_lock() Michael Ellerman
2013-12-23 12:46 ` [PATCH 2/3] powerpc/xmon: Fix timeout loop " Michael Ellerman
2013-12-23 12:46 ` [PATCH 3/3] powerpc/xmon: Don't signal we've entered until we're finished printing Michael Ellerman
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).