Messages in this thread | | | Date | Fri, 1 Nov 2019 11:09:03 +0100 | From | Peter Zijlstra <> | Subject | Re: [PATCH RFC 1/6] perf/x86: Add perf text poke event |
| |
On Fri, Nov 01, 2019 at 11:04:40AM +0100, Peter Zijlstra wrote:
> I'm thinking something along the lines of: > > static uintptr_t nosync_addr; > static u32 nosync_insn; > > int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn) > { > const u32 break = // some_breakpoint_insn; > uintptr_t tp = (uintptr_t)addr; > int ret; > > lockdep_assert_held(&text_mutex); > > /* A64 instructions must be word aligned */ > if (tp & 0x3) > return -EINVAL; > > if (perf_text_poke_update_enabled()) { > > nosync_insn = insn; > smp_store_release(&nosync_addr, tp); > > ret = aarch64_insn_write(addr, break); > if (ret == 0) > __flush_icache_range(tp, tp + AARCH64_INSN_SIZE); > > perf_event_text_poke(....); > } > > ret = aarch64_insn_write(addr, insn); > if (ret == 0) > __flush_icache_range(tp, tp + AARCH64_INSN_SIZE);
// barrier that guarantees iflush completion ? dsb(osh) ?
WRITE_ONCE(nosync_addr, NULL);
> return ret; > } > > And have the 'break' handler do: > > aarch64_insn_break_handler(struct pt_regs *regs) > { > unsigned long addr = smp_load_acquire(&nosync_addr); > u32 insn = nosync_insn; > > if (regs->ip != addr) > return; > > // emulate @insn > } > > I understood from Will the whole nosync scheme only works for a limited > set of instructions, but you only have to implement emulation for the > actual instructions used of course. > > (which is what we do on x86) > > Does this sound workable?
| |