On Tue, Aug 31, 2021 at 01:12:26PM +0000, Christophe Leroy wrote: > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig > index 36b72d972568..a0fe69d8ec83 100644 > --- a/arch/powerpc/Kconfig > +++ b/arch/powerpc/Kconfig > @@ -247,6 +247,7 @@ config PPC > select HAVE_SOFTIRQ_ON_OWN_STACK > select HAVE_STACKPROTECTOR if PPC32 && > $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2) > select HAVE_STACKPROTECTOR if PPC64 && > $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r13) > + select HAVE_STATIC_CALL if PPC32 > select HAVE_SYSCALL_TRACEPOINTS > select HAVE_VIRT_CPU_ACCOUNTING > select HUGETLB_PAGE_SIZE_VARIABLE if PPC_BOOK3S_64 && HUGETLB_PAGE > diff --git a/arch/powerpc/include/asm/static_call.h > b/arch/powerpc/include/asm/static_call.h > new file mode 100644 > index 000000000000..2402c6d32439 > --- /dev/null > +++ b/arch/powerpc/include/asm/static_call.h > @@ -0,0 +1,25 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#ifndef _ASM_POWERPC_STATIC_CALL_H > +#define _ASM_POWERPC_STATIC_CALL_H > + > +#define __POWERPC_SCT(name, inst) \ > + asm(".pushsection .text, \"ax\" \n" \ > + ".align 5 \n" \ > + ".globl " STATIC_CALL_TRAMP_STR(name) " \n" \ > + STATIC_CALL_TRAMP_STR(name) ": \n" \ > + inst " \n" \ > + " lis 12,1f@ha \n" \ > + " lwz 12,1f@l(12) \n" \ > + " mtctr 12 \n" \ > + " bctr \n" \ > + "1: .long 0 \n" \ > + " nop \n" \ > + " nop \n" \ > + ".type " STATIC_CALL_TRAMP_STR(name) ", @function \n" \ > + ".size " STATIC_CALL_TRAMP_STR(name) ", . - " > STATIC_CALL_TRAMP_STR(name) " \n" \ > + ".popsection \n") > + > +#define ARCH_DEFINE_STATIC_CALL_TRAMP(name, func) __POWERPC_SCT(name, "b > " #func) > +#define ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) __POWERPC_SCT(name, > "blr") > + > +#endif /* _ASM_POWERPC_STATIC_CALL_H */
> diff --git a/arch/powerpc/kernel/static_call.c > b/arch/powerpc/kernel/static_call.c > new file mode 100644 > index 000000000000..e5e78205ccb4 > --- /dev/null > +++ b/arch/powerpc/kernel/static_call.c > @@ -0,0 +1,36 @@ > +// SPDX-License-Identifier: GPL-2.0 > +#include <linux/memory.h> > +#include <linux/static_call.h> > + > +#include <asm/code-patching.h> > + > +void arch_static_call_transform(void *site, void *tramp, void *func, bool > tail) > +{ > + int err; > + unsigned long target = (long)func; > + bool is_short = is_offset_in_branch_range((long)target - (long)tramp); > + > + if (!tramp) > + return; > + > + mutex_lock(&text_mutex); > + > + if (func && !is_short) { > + err = patch_instruction(tramp + 20, ppc_inst(target)); > + if (err) > + goto out; > + } > + > + if (!func) > + err = patch_instruction(tramp, ppc_inst(PPC_RAW_BLR())); > + else if (is_short) > + err = patch_branch(tramp, target, 0); > + else > + err = patch_instruction(tramp, ppc_inst(PPC_RAW_NOP())); > +out: > + mutex_unlock(&text_mutex); > + > + if (err) > + panic("%s: patching failed %pS at %pS\n", __func__, func, > tramp); > +} > +EXPORT_SYMBOL_GPL(arch_static_call_transform); Yes, this should work nicely! Since you have the two nop's at the end, you could frob in an optimization for __static_call_return0 without too much issue. Replace the two nops with (excuse my ppc asm): li r3, 0 blr and augment arch_static_call_transform() with something like: if (func == &__static_call_return0) err = patch_branch(tramp, tramp+24, 0);