Commit a9af97aa authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Michael Ellerman

powerpc/64s: msgclr when handling doorbell exceptions from system reset

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: default avatarGautham R. Shenoy <ego@linux.vnet.ibm.com>
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 771d4304
...@@ -56,6 +56,19 @@ static inline void ppc_msgsync(void) ...@@ -56,6 +56,19 @@ static inline void ppc_msgsync(void)
: : "i" (CPU_FTR_HVMODE|CPU_FTR_ARCH_300)); : : "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 */ #else /* CONFIG_PPC_BOOK3S */
#define PPC_DBELL_MSGTYPE PPC_DBELL #define PPC_DBELL_MSGTYPE PPC_DBELL
......
...@@ -220,6 +220,7 @@ ...@@ -220,6 +220,7 @@
#define PPC_INST_MSGCLR 0x7c0001dc #define PPC_INST_MSGCLR 0x7c0001dc
#define PPC_INST_MSGSYNC 0x7c0006ec #define PPC_INST_MSGSYNC 0x7c0006ec
#define PPC_INST_MSGSNDP 0x7c00011c #define PPC_INST_MSGSNDP 0x7c00011c
#define PPC_INST_MSGCLRP 0x7c00015c
#define PPC_INST_MTTMR 0x7c0003dc #define PPC_INST_MTTMR 0x7c0003dc
#define PPC_INST_NOP 0x60000000 #define PPC_INST_NOP 0x60000000
#define PPC_INST_PASTE 0x7c20070d #define PPC_INST_PASTE 0x7c20070d
...@@ -409,6 +410,8 @@ ...@@ -409,6 +410,8 @@
___PPC_RB(b)) ___PPC_RB(b))
#define PPC_MSGSNDP(b) stringify_in_c(.long PPC_INST_MSGSNDP | \ #define PPC_MSGSNDP(b) stringify_in_c(.long PPC_INST_MSGSNDP | \
___PPC_RB(b)) ___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 | \ #define PPC_POPCNTB(a, s) stringify_in_c(.long PPC_INST_POPCNTB | \
__PPC_RA(a) | __PPC_RS(s)) __PPC_RA(a) | __PPC_RS(s))
#define PPC_POPCNTD(a, s) stringify_in_c(.long PPC_INST_POPCNTD | \ #define PPC_POPCNTD(a, s) stringify_in_c(.long PPC_INST_POPCNTD | \
......
...@@ -746,6 +746,7 @@ int main(void) ...@@ -746,6 +746,7 @@ int main(void)
#endif #endif
DEFINE(PPC_DBELL_SERVER, PPC_DBELL_SERVER); DEFINE(PPC_DBELL_SERVER, PPC_DBELL_SERVER);
DEFINE(PPC_DBELL_MSGTYPE, PPC_DBELL_MSGTYPE);
#ifdef CONFIG_PPC_8xx #ifdef CONFIG_PPC_8xx
DEFINE(VIRT_IMMR_BASE, (u64)__fix_to_virt(FIX_IMMR_BASE)); DEFINE(VIRT_IMMR_BASE, (u64)__fix_to_virt(FIX_IMMR_BASE));
......
...@@ -1611,6 +1611,25 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) ...@@ -1611,6 +1611,25 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
bl kernel_bad_stack bl kernel_bad_stack
b 1b 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 * Called from arch_local_irq_enable when an interrupt needs
* to be resent. r3 contains 0x500, 0x900, 0xa00 or 0xe80 to indicate * to be resent. r3 contains 0x500, 0x900, 0xa00 or 0xe80 to indicate
...@@ -1636,13 +1655,13 @@ _GLOBAL(__replay_interrupt) ...@@ -1636,13 +1655,13 @@ _GLOBAL(__replay_interrupt)
beq hardware_interrupt_common beq hardware_interrupt_common
BEGIN_FTR_SECTION BEGIN_FTR_SECTION
cmpwi r3,0xe80 cmpwi r3,0xe80
beq h_doorbell_common beq h_doorbell_common_msgclr
cmpwi r3,0xea0 cmpwi r3,0xea0
beq h_virt_irq_common beq h_virt_irq_common
cmpwi r3,0xe60 cmpwi r3,0xe60
beq hmi_exception_common beq hmi_exception_common
FTR_SECTION_ELSE FTR_SECTION_ELSE
cmpwi r3,0xa00 cmpwi r3,0xa00
beq doorbell_super_common beq doorbell_super_common_msgclr
ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE)
blr blr
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment