powerpc: Use static call for get_irq()
__do_irq() inconditionnaly calls ppc_md.get_irq() That's definitely a hot path. At the time being ppc_md.get_irq address is read every time from ppc_md structure. Replace that call by a static call, and initialise that call after ppc_md.init_IRQ() has set ppc_md.get_irq. Emit a warning and don't set the static call if ppc_md.init_IRQ() is still NULL, that way the kernel won't blow up if for some reason ppc_md.get_irq() doesn't get properly set. With the patch: 00000000 <__SCT__ppc_get_irq>: 0: 48 00 00 20 b 20 <__static_call_return0> <== Replaced by 'b <ppc_md.get_irq>' at runtime ... 00000020 <__static_call_return0>: 20: 38 60 00 00 li r3,0 24: 4e 80 00 20 blr ... 00000058 <__do_irq>: ... 64: 48 00 00 01 bl 64 <__do_irq+0xc> 64: R_PPC_REL24 __SCT__ppc_get_irq 68: 2c 03 00 00 cmpwi r3,0 ... Before the patch: 00000038 <__do_irq>: ... 3c: 3d 20 00 00 lis r9,0 3e: R_PPC_ADDR16_HA ppc_md+0x1c ... 44: 81 29 00 00 lwz r9,0(r9) 46: R_PPC_ADDR16_LO ppc_md+0x1c ... 4c: 7d 29 03 a6 mtctr r9 50: 4e 80 04 21 bctrl 54: 2c 03 00 00 cmpwi r3,0 ... On PPC64 which doesn't implement static calls yet we get: 00000000000000d0 <__do_irq>: ... dc: 00 00 22 3d addis r9,r2,0 dc: R_PPC64_TOC16_HA .data+0x8 ... e4: 00 00 89 e9 ld r12,0(r9) e4: R_PPC64_TOC16_LO_DS .data+0x8 ... f0: a6 03 89 7d mtctr r12 f4: 18 00 41 f8 std r2,24(r1) f8: 21 04 80 4e bctrl fc: 18 00 41 e8 ld r2,24(r1) ... So on PPC64 that's similar to what we get without static calls. But at least until ppc_md.get_irq() is set the call is to __static_call_return0. Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/afb92085f930651d8b1063e4d4bf0396c80ebc7d.1647002274.git.christophe.leroy@csgroup.eu
This commit is contained in:
parent
a1ae431705
commit
e59596a2d6
|
@ -52,6 +52,7 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/pgtable.h>
|
||||
#include <linux/static_call.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/interrupt.h>
|
||||
|
@ -729,6 +730,8 @@ static __always_inline void call_do_irq(struct pt_regs *regs, void *sp)
|
|||
);
|
||||
}
|
||||
|
||||
DEFINE_STATIC_CALL_RET0(ppc_get_irq, *ppc_md.get_irq);
|
||||
|
||||
void __do_irq(struct pt_regs *regs)
|
||||
{
|
||||
unsigned int irq;
|
||||
|
@ -740,7 +743,7 @@ void __do_irq(struct pt_regs *regs)
|
|||
*
|
||||
* This will typically lower the interrupt line to the CPU
|
||||
*/
|
||||
irq = ppc_md.get_irq();
|
||||
irq = static_call(ppc_get_irq)();
|
||||
|
||||
/* We can hard enable interrupts now to allow perf interrupts */
|
||||
if (should_hard_irq_enable())
|
||||
|
@ -808,6 +811,9 @@ void __init init_IRQ(void)
|
|||
|
||||
if (ppc_md.init_IRQ)
|
||||
ppc_md.init_IRQ();
|
||||
|
||||
if (!WARN_ON(!ppc_md.get_irq))
|
||||
static_call_update(ppc_get_irq, ppc_md.get_irq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOKE_OR_40x
|
||||
|
|
Loading…
Reference in New Issue