powerpc/64s: msgclr when handling doorbell exceptions from system reset
authorNicholas Piggin <npiggin@gmail.com>
Tue, 13 Jun 2017 13:05:48 +0000 (23:05 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 19 Jun 2017 09:46:27 +0000 (19:46 +1000)
msgsnd doorbell exceptions are cleared when the doorbell interrupt is
taken. However if a doorbell exception causes a system reset interrupt
wake from power saving state, the message is not cleared. Processing
the doorbell from the system reset interrupt requires msgclr to avoid
taking the exception again.

Testing this plus the previous wakup direct patch gives:

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

Net speedup is +10% for same core, and +3% for different core.

Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/dbell.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/exceptions-64s.S

index f70cbfe0ec045d54b90fbbe121dd5c395ad233da..9f2ae0d25e150418f26762d6864646b103196a42 100644 (file)
@@ -56,6 +56,19 @@ static inline void ppc_msgsync(void)
                                : : "i" (CPU_FTR_HVMODE|CPU_FTR_ARCH_300));
 }
 
+static inline void _ppc_msgclr(u32 msg)
+{
+       __asm__ __volatile__ (ASM_FTR_IFSET(PPC_MSGCLR(%1), PPC_MSGCLRP(%1), %0)
+                               : : "i" (CPU_FTR_HVMODE), "r" (msg));
+}
+
+static inline void ppc_msgclr(enum ppc_dbell type)
+{
+       u32 msg = PPC_DBELL_TYPE(type);
+
+       _ppc_msgclr(msg);
+}
+
 #else /* CONFIG_PPC_BOOK3S */
 
 #define PPC_DBELL_MSGTYPE              PPC_DBELL
index 3b6bbf5a86836bf02890e76a235b724ad34fc844..4e2cf719c9b2575eb5638ce29a9c9b28b9857643 100644 (file)
 #define PPC_INST_MSGCLR                        0x7c0001dc
 #define PPC_INST_MSGSYNC               0x7c0006ec
 #define PPC_INST_MSGSNDP               0x7c00011c
+#define PPC_INST_MSGCLRP               0x7c00015c
 #define PPC_INST_MTTMR                 0x7c0003dc
 #define PPC_INST_NOP                   0x60000000
 #define PPC_INST_PASTE                 0x7c20070d
                                        ___PPC_RB(b))
 #define PPC_MSGSNDP(b)         stringify_in_c(.long PPC_INST_MSGSNDP | \
                                        ___PPC_RB(b))
+#define PPC_MSGCLRP(b)         stringify_in_c(.long PPC_INST_MSGCLRP | \
+                                       ___PPC_RB(b))
 #define PPC_POPCNTB(a, s)      stringify_in_c(.long PPC_INST_POPCNTB | \
                                        __PPC_RA(a) | __PPC_RS(s))
 #define PPC_POPCNTD(a, s)      stringify_in_c(.long PPC_INST_POPCNTD | \
index e15c178ba079dcfe0940c83e48cc417557a04539..9624851ca2768cc22f0d75456fa325bad5dd9ad6 100644 (file)
@@ -746,6 +746,7 @@ int main(void)
 #endif
 
        DEFINE(PPC_DBELL_SERVER, PPC_DBELL_SERVER);
+       DEFINE(PPC_DBELL_MSGTYPE, PPC_DBELL_MSGTYPE);
 
 #ifdef CONFIG_PPC_8xx
        DEFINE(VIRT_IMMR_BASE, (u64)__fix_to_virt(FIX_IMMR_BASE));
index 2f700a15bfa3ee5d8da0e6f2c05429bf4a3bc6e2..1752beefee69a2cc89c28993aa5edb7107498d72 100644 (file)
@@ -1611,6 +1611,25 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
        bl      kernel_bad_stack
        b       1b
 
+/*
+ * When doorbell is triggered from system reset wakeup, the message is
+ * not cleared, so it would fire again when EE is enabled.
+ *
+ * When coming from local_irq_enable, there may be the same problem if
+ * we were hard disabled.
+ *
+ * Execute msgclr to clear pending exceptions before handling it.
+ */
+h_doorbell_common_msgclr:
+       LOAD_REG_IMMEDIATE(r3, PPC_DBELL_MSGTYPE << (63-36))
+       PPC_MSGCLR(3)
+       b       h_doorbell_common
+
+doorbell_super_common_msgclr:
+       LOAD_REG_IMMEDIATE(r3, PPC_DBELL_MSGTYPE << (63-36))
+       PPC_MSGCLRP(3)
+       b       doorbell_super_common
+
 /*
  * Called from arch_local_irq_enable when an interrupt needs
  * to be resent. r3 contains 0x500, 0x900, 0xa00 or 0xe80 to indicate
@@ -1636,13 +1655,13 @@ _GLOBAL(__replay_interrupt)
        beq     hardware_interrupt_common
 BEGIN_FTR_SECTION
        cmpwi   r3,0xe80
-       beq     h_doorbell_common
+       beq     h_doorbell_common_msgclr
        cmpwi   r3,0xea0
        beq     h_virt_irq_common
        cmpwi   r3,0xe60
        beq     hmi_exception_common
 FTR_SECTION_ELSE
        cmpwi   r3,0xa00
-       beq     doorbell_super_common
+       beq     doorbell_super_common_msgclr
 ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
        blr