Re: [PATCH v2 3/4] x86/static_call: Add out-of-line static call implementation

From: Peter Zijlstra
Date: Mon Nov 26 2018 - 10:44:20 EST


On Mon, Nov 26, 2018 at 07:54:59AM -0600, Josh Poimboeuf wrote:

> +void static_call_bp_handler(void);
> +void *bp_handler_dest;
> +
> +asm(".pushsection .text, \"ax\" \n"
> + ".globl static_call_bp_handler \n"
> + ".type static_call_bp_handler, @function \n"
> + "static_call_bp_handler: \n"
> + "ANNOTATE_RETPOLINE_SAFE \n"
> + "jmp *bp_handler_dest \n"
> + ".popsection \n");
> +
> +void arch_static_call_transform(void *site, void *tramp, void *func)
> +{
> + s32 dest_relative;
> + unsigned long insn;
> + unsigned char insn_opcode;
> + unsigned char opcodes[CALL_INSN_SIZE];
> +
> + insn = (unsigned long)tramp;
> +
> + mutex_lock(&text_mutex);
> +
> + insn_opcode = *(unsigned char *)insn;
> + if (insn_opcode != 0xe8 && insn_opcode != 0xe9) {
> + WARN_ONCE(1, "unexpected static call insn opcode 0x%x at %pS",
> + insn_opcode, (void *)insn);
> + goto done;
> + }
> +
> + dest_relative = (long)(func) - (long)(insn + CALL_INSN_SIZE);
> +
> + opcodes[0] = insn_opcode;
> + memcpy(&opcodes[1], &dest_relative, CALL_INSN_SIZE - 1);
> +
> + /* Set up the variable for the breakpoint handler: */
> + bp_handler_dest = func;
> +
> + /* Patch the call site: */
> + text_poke_bp((void *)insn, opcodes, CALL_INSN_SIZE,
> + static_call_bp_handler);

I'm confused by the whole static_call_bp_handler thing; why not jump
straight to @func ?

Also, what guarantees this other thread will have gotten from
static_call_bp_handler and executed the actual indirect JMP instruction
by the time we re-write @bp_handler_dest again?

> +done:
> + mutex_unlock(&text_mutex);
> +}