linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Nicholas Piggin <npiggin@gmail.com>
To: linuxppc-dev@lists.ozlabs.org
Cc: Nicholas Piggin <npiggin@gmail.com>,
	"Gautham R . Shenoy" <ego@linux.vnet.ibm.com>,
	"Vaidyanathan Srinivasan" <svaidy@linux.vnet.ibm.com>
Subject: [PATCH 03/13] powerpc/64s: idle process interrupts from system reset wakeup
Date: Tue, 13 Jun 2017 23:05:47 +1000	[thread overview]
Message-ID: <20170613130557.26315-4-npiggin@gmail.com> (raw)
In-Reply-To: <20170613130557.26315-1-npiggin@gmail.com>

When the CPU wakes from low power state, it begins at the system reset
interrupt with the exception that caused the wakeup encoded in SRR1.

Today, powernv idle wakeup ignores the wakeup reason (except a special
case for HMI), and the regular interrupt corresponding to the
exception will fire after the idle wakeup exits.

Change this to replay the interrupt from the idle wakeup before
interrupts are hard-enabled.

Test on POWER8 of context_switch selftests benchmark with polling idle
disabled (e.g., always nap, giving cross-CPU IPIs) gives the following
results:

                                original         wakeup direct
Different threads, same core:   315k/s           264k/s
Different cores:                235k/s           242k/s

There is a slowdown for doorbell IPI (same core) case because system
reset wakeup does not clear the message and the doorbell interrupt
fires again needlessly.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/hw_irq.h     |  2 ++
 arch/powerpc/kernel/irq.c             | 29 +++++++++++++++++++++++++++++
 arch/powerpc/platforms/powernv/idle.c | 10 ++++++++--
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index f06112cf8734..8366bdc69988 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -32,6 +32,7 @@
 #ifndef __ASSEMBLY__
 
 extern void __replay_interrupt(unsigned int vector);
+extern void __replay_wakeup_interrupt(unsigned long srr1);
 
 extern void timer_interrupt(struct pt_regs *);
 extern void performance_monitor_exception(struct pt_regs *regs);
@@ -130,6 +131,7 @@ static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
 
 extern bool prep_irq_for_idle(void);
 extern bool prep_irq_for_idle_irqsoff(void);
+extern void irq_set_pending_from_srr1(unsigned long srr1);
 
 #define fini_irq_for_idle_irqsoff() trace_hardirqs_off();
 
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index be32cec28107..76224869059d 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -348,6 +348,7 @@ bool prep_irq_for_idle(void)
 	return true;
 }
 
+#ifdef CONFIG_PPC_BOOK3S
 /*
  * This is for idle sequences that return with IRQs off, but the
  * idle state itself wakes on interrupt. Tell the irq tracer that
@@ -379,6 +380,34 @@ bool prep_irq_for_idle_irqsoff(void)
 }
 
 /*
+ * Take the SRR1 wakeup reason, index into this table to find the
+ * appropriate irq_happened bit.
+ */
+static const u8 srr1_to_lazyirq[0x10] = {
+	0, 0, 0,
+	PACA_IRQ_DBELL,
+	0,
+	PACA_IRQ_DBELL,
+	PACA_IRQ_DEC,
+	0,
+	PACA_IRQ_EE,
+	PACA_IRQ_EE,
+	PACA_IRQ_HMI,
+	0, 0, 0, 0, 0 };
+
+void irq_set_pending_from_srr1(unsigned long srr1)
+{
+	unsigned int idx = (srr1 & SRR1_WAKEMASK_P8) >> 18;
+
+	/*
+	 * The 0 index (SRR1[42:45]=b0000) must always evaluate to 0,
+	 * so this can be called unconditionally with srr1 wake reason.
+	 */
+	local_paca->irq_happened |= srr1_to_lazyirq[idx];
+}
+#endif /* CONFIG_PPC_BOOK3S */
+
+/*
  * Force a replay of the external interrupt handler on this CPU.
  */
 void force_external_irq_replay(void)
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index f188d84d9c59..1028df82cd2f 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -302,7 +302,10 @@ static unsigned long __power7_idle_type(unsigned long type)
 
 void power7_idle_type(unsigned long type)
 {
-	__power7_idle_type(type);
+	unsigned long srr1;
+
+	srr1 = __power7_idle_type(type);
+	irq_set_pending_from_srr1(srr1);
 }
 
 void power7_idle(void)
@@ -337,7 +340,10 @@ static unsigned long __power9_idle_type(unsigned long stop_psscr_val,
 void power9_idle_type(unsigned long stop_psscr_val,
 				      unsigned long stop_psscr_mask)
 {
-	__power9_idle_type(stop_psscr_val, stop_psscr_mask);
+	unsigned long srr1;
+
+	srr1 = __power9_idle_type(stop_psscr_val, stop_psscr_mask);
+	irq_set_pending_from_srr1(srr1);
 }
 
 /*
-- 
2.11.0

  parent reply	other threads:[~2017-06-13 13:06 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-13 13:05 [PATCH 00/13 v3] idle performance improvements Nicholas Piggin
2017-06-13 13:05 ` [PATCH 01/13] powerpc/64s: idle move soft interrupt mask logic into C code Nicholas Piggin
2017-06-19 12:25   ` [01/13] " Michael Ellerman
2017-06-13 13:05 ` [PATCH 02/13] powerpc/64s: idle hotplug lazy-irq simplification Nicholas Piggin
2017-06-19 12:25   ` [02/13] " Michael Ellerman
2017-06-13 13:05 ` Nicholas Piggin [this message]
2017-06-13 13:28   ` [PATCH 03/13] powerpc/64s: idle process interrupts from system reset wakeup Nicholas Piggin
2017-06-14 11:29     ` Michael Ellerman
2017-06-19 12:25   ` [03/13] " Michael Ellerman
2017-06-13 13:05 ` [PATCH 04/13] powerpc/64s: msgclr when handling doorbell exceptions Nicholas Piggin
2017-06-19 12:25   ` [04/13] " Michael Ellerman
2017-06-13 13:05 ` [PATCH 05/13] powerpc/64s: interrupt replay balance the return branch predictor Nicholas Piggin
2017-06-19 12:25   ` [05/13] " Michael Ellerman
2017-06-13 13:05 ` [PATCH 06/13] powerpc/64s: idle branch to handler with virtual mode offset Nicholas Piggin
2017-06-19 12:25   ` [06/13] " Michael Ellerman
2017-06-13 13:05 ` [PATCH 07/13] powerpc/64s: idle avoid SRR usage in idle sleep/wake paths Nicholas Piggin
2017-06-15 12:11   ` Nicholas Piggin
2017-06-19 12:25   ` [07/13] " Michael Ellerman
2017-06-13 13:05 ` [PATCH 08/13] powerpc/64s: idle hmi wakeup is unlikely Nicholas Piggin
2017-06-19 12:25   ` [08/13] " Michael Ellerman
2017-06-13 13:05 ` [PATCH 09/13] powerpc/64s: cpuidle set polling before enabling irqs Nicholas Piggin
2017-06-14 11:40   ` Michael Ellerman
2017-06-14 11:50     ` Nicholas Piggin
2017-06-14 13:05       ` Michael Ellerman
2017-06-13 13:05 ` [PATCH 10/13] powerpc/64s: cpuidle read mostly for common globals Nicholas Piggin
2017-06-13 13:05 ` [PATCH 11/13] powerpc/64s: cpuidle no memory barrier after break from idle Nicholas Piggin
2017-06-13 13:05 ` [PATCH 12/13] powerpc/64: runlatch CTRL[RUN] set optimisation Nicholas Piggin
2017-06-14 11:38   ` Michael Ellerman
2017-06-14 13:44     ` Nicholas Piggin
2017-06-15  9:35       ` Michael Ellerman
2017-06-13 13:05 ` [PATCH 13/13] powerpc/64s: idle runlatch switch is done with MSR[EE]=0 Nicholas Piggin
2017-06-19 12:25   ` [13/13] " Michael Ellerman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170613130557.26315-4-npiggin@gmail.com \
    --to=npiggin@gmail.com \
    --cc=ego@linux.vnet.ibm.com \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=svaidy@linux.vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).