From nobody Tue Dec 2 02:52:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AAE0632E140; Mon, 17 Nov 2025 12:41:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383282; cv=none; b=WrAfUW8EM6AmiXJJgMf867NIgcq+lBOVjtjsN/hYQnTU41iNNibnmid4v6ZO4Sa+qNqMV+lj+zjwLLfbAxmxSdnuqaFpT4LPnqV7Jr3+ttD/8oK1cioSeOLSf+wOT8bBaBGgTsSowxrufOOuIFId59Tk/HcelTOeLQ2TD8RDuhA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383282; c=relaxed/simple; bh=yjQSutv+PRPuxVWoLTWx0ZnuJMKaycwr6No20fC2bV4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Y83XHT4GQ0Hth3ksRsn6JhiXechEISvz0C3IDKlqrssn4cJxRA8j/9EuFJMGSX1nD1ebPUX+asahgaNkLkUH3jjO+gZ3i6xrNDxcZ9FS1lz1Z3DyDMiomOiF3C6xdSdQgmjwcLOsNTHF9jpaJ8ulTHmyqaLgtqHxcTc58pq+Q0A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Jdw0gcJE; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Jdw0gcJE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CA027C4CEF1; Mon, 17 Nov 2025 12:41:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763383282; bh=yjQSutv+PRPuxVWoLTWx0ZnuJMKaycwr6No20fC2bV4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Jdw0gcJEN6R2llFhQRFnVmahQKHonD/DJHHathwL/BlrSQ1uI/RlVmapHpcqO2Cyo az8zzUI1MZz5tuF/3ooUwKM+1bTfsVg9quavN+wiICkk1OxSn4PDkXkq4WXGq+P6Pz ie0XcArxvgOr8viIisaqTmIGkfNNIsZNOJ6LFwe7ncmKoyTPlRh/VwO+rXFL5dnS2C 611B4VjgaSKaBahGGoYyok6FWEawppuGd7cU9Nv6QSFFTvdSAZ14iMIu76IpA9qYUR wZwy/k5SgrwirhcX9e3AbUhlcTV6toDird6zSvBqInITZgS6Ik/erfZYHYMq/+SRE6 axOTHhfth2INA== From: Jiri Olsa To: Oleg Nesterov , Masami Hiramatsu , Peter Zijlstra , Andrii Nakryiko Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, x86@kernel.org, Song Liu , Yonghong Song , John Fastabend , Steven Rostedt , Ingo Molnar , David Laight Subject: [RFC PATCH 1/8] uprobe/x86: Introduce struct arch_uprobe_xol object Date: Mon, 17 Nov 2025 13:40:50 +0100 Message-ID: <20251117124057.687384-2-jolsa@kernel.org> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117124057.687384-1-jolsa@kernel.org> References: <20251117124057.687384-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Mov xol data into separate arch_uprobe_xol object so we can hold more of them in following changes. Signed-off-by: Jiri Olsa --- arch/x86/include/asm/uprobes.h | 16 ++++--- arch/x86/kernel/uprobes.c | 78 +++++++++++++++++----------------- 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h index 1ee2e5115955..819e35aa61c4 100644 --- a/arch/x86/include/asm/uprobes.h +++ b/arch/x86/include/asm/uprobes.h @@ -27,12 +27,7 @@ enum { =20 struct uprobe_xol_ops; =20 -struct arch_uprobe { - union { - u8 insn[MAX_UINSN_BYTES]; - u8 ixol[MAX_UINSN_BYTES]; - }; - +struct arch_uprobe_xol { const struct uprobe_xol_ops *ops; =20 union { @@ -50,6 +45,15 @@ struct arch_uprobe { u8 ilen; } push; }; +}; + +struct arch_uprobe { + union { + u8 insn[MAX_UINSN_BYTES]; + u8 ixol[MAX_UINSN_BYTES]; + }; + + struct arch_uprobe_xol xol; =20 unsigned long flags; }; diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 845aeaf36b8d..fb9457b29dbc 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -560,14 +560,14 @@ static void riprel_analyze(struct arch_uprobe *auprob= e, struct insn *insn) */ if (reg !=3D 6 && reg2 !=3D 6) { reg2 =3D 6; - auprobe->defparam.fixups |=3D UPROBE_FIX_RIP_SI; + auprobe->xol.defparam.fixups |=3D UPROBE_FIX_RIP_SI; } else if (reg !=3D 7 && reg2 !=3D 7) { reg2 =3D 7; - auprobe->defparam.fixups |=3D UPROBE_FIX_RIP_DI; + auprobe->xol.defparam.fixups |=3D UPROBE_FIX_RIP_DI; /* TODO (paranoia): force maskmovq to not use di */ } else { reg2 =3D 3; - auprobe->defparam.fixups |=3D UPROBE_FIX_RIP_BX; + auprobe->xol.defparam.fixups |=3D UPROBE_FIX_RIP_BX; } /* * Point cursor at the modrm byte. The next 4 bytes are the @@ -586,9 +586,9 @@ static void riprel_analyze(struct arch_uprobe *auprobe,= struct insn *insn) static inline unsigned long * scratch_reg(struct arch_uprobe *auprobe, struct pt_regs *regs) { - if (auprobe->defparam.fixups & UPROBE_FIX_RIP_SI) + if (auprobe->xol.defparam.fixups & UPROBE_FIX_RIP_SI) return ®s->si; - if (auprobe->defparam.fixups & UPROBE_FIX_RIP_DI) + if (auprobe->xol.defparam.fixups & UPROBE_FIX_RIP_DI) return ®s->di; return ®s->bx; } @@ -599,18 +599,18 @@ scratch_reg(struct arch_uprobe *auprobe, struct pt_re= gs *regs) */ static void riprel_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *re= gs) { - if (auprobe->defparam.fixups & UPROBE_FIX_RIP_MASK) { + if (auprobe->xol.defparam.fixups & UPROBE_FIX_RIP_MASK) { struct uprobe_task *utask =3D current->utask; unsigned long *sr =3D scratch_reg(auprobe, regs); =20 utask->autask.saved_scratch_register =3D *sr; - *sr =3D utask->vaddr + auprobe->defparam.ilen; + *sr =3D utask->vaddr + auprobe->xol.defparam.ilen; } } =20 static void riprel_post_xol(struct arch_uprobe *auprobe, struct pt_regs *r= egs) { - if (auprobe->defparam.fixups & UPROBE_FIX_RIP_MASK) { + if (auprobe->xol.defparam.fixups & UPROBE_FIX_RIP_MASK) { struct uprobe_task *utask =3D current->utask; unsigned long *sr =3D scratch_reg(auprobe, regs); =20 @@ -1265,16 +1265,16 @@ static int default_post_xol_op(struct arch_uprobe *= auprobe, struct pt_regs *regs struct uprobe_task *utask =3D current->utask; =20 riprel_post_xol(auprobe, regs); - if (auprobe->defparam.fixups & UPROBE_FIX_IP) { + if (auprobe->xol.defparam.fixups & UPROBE_FIX_IP) { long correction =3D utask->vaddr - utask->xol_vaddr; regs->ip +=3D correction; - } else if (auprobe->defparam.fixups & UPROBE_FIX_CALL) { + } else if (auprobe->xol.defparam.fixups & UPROBE_FIX_CALL) { regs->sp +=3D sizeof_long(regs); /* Pop incorrect return address */ - if (emulate_push_stack(regs, utask->vaddr + auprobe->defparam.ilen)) + if (emulate_push_stack(regs, utask->vaddr + auprobe->xol.defparam.ilen)) return -ERESTART; } /* popf; tell the caller to not touch TF */ - if (auprobe->defparam.fixups & UPROBE_FIX_SETF) + if (auprobe->xol.defparam.fixups & UPROBE_FIX_SETF) utask->autask.saved_tf =3D true; =20 return 0; @@ -1293,7 +1293,7 @@ static const struct uprobe_xol_ops default_xol_ops = =3D { =20 static bool branch_is_call(struct arch_uprobe *auprobe) { - return auprobe->branch.opc1 =3D=3D 0xe8; + return auprobe->xol.branch.opc1 =3D=3D 0xe8; } =20 #define CASE_COND \ @@ -1329,7 +1329,7 @@ static bool check_jmp_cond(struct arch_uprobe *auprob= e, struct pt_regs *regs) { unsigned long flags =3D regs->flags; =20 - switch (auprobe->branch.opc1) { + switch (auprobe->xol.branch.opc1) { #define DO(expr) \ return expr; CASE_COND @@ -1346,8 +1346,8 @@ static bool check_jmp_cond(struct arch_uprobe *auprob= e, struct pt_regs *regs) =20 static bool branch_emulate_op(struct arch_uprobe *auprobe, struct pt_regs = *regs) { - unsigned long new_ip =3D regs->ip +=3D auprobe->branch.ilen; - unsigned long offs =3D (long)auprobe->branch.offs; + unsigned long new_ip =3D regs->ip +=3D auprobe->xol.branch.ilen; + unsigned long offs =3D (long)auprobe->xol.branch.offs; =20 if (branch_is_call(auprobe)) { /* @@ -1371,11 +1371,11 @@ static bool branch_emulate_op(struct arch_uprobe *a= uprobe, struct pt_regs *regs) =20 static bool push_emulate_op(struct arch_uprobe *auprobe, struct pt_regs *r= egs) { - unsigned long *src_ptr =3D (void *)regs + auprobe->push.reg_offset; + unsigned long *src_ptr =3D (void *)regs + auprobe->xol.push.reg_offset; =20 if (emulate_push_stack(regs, *src_ptr)) return false; - regs->ip +=3D auprobe->push.ilen; + regs->ip +=3D auprobe->xol.push.ilen; return true; } =20 @@ -1469,16 +1469,16 @@ static int branch_setup_xol_ops(struct arch_uprobe = *auprobe, struct insn *insn) } =20 setup: - auprobe->branch.opc1 =3D opc1; - auprobe->branch.ilen =3D insn->length; - auprobe->branch.offs =3D insn->immediate.value; + auprobe->xol.branch.opc1 =3D opc1; + auprobe->xol.branch.ilen =3D insn->length; + auprobe->xol.branch.offs =3D insn->immediate.value; =20 - auprobe->ops =3D &branch_xol_ops; + auprobe->xol.ops =3D &branch_xol_ops; return 0; } =20 /* Returns -ENOSYS if push_xol_ops doesn't handle this insn */ -static int push_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *in= sn) +static int push_setup_xol_ops(struct arch_uprobe_xol *xol, struct insn *in= sn) { u8 opc1 =3D OPCODE1(insn), reg_offset =3D 0; =20 @@ -1552,9 +1552,9 @@ static int push_setup_xol_ops(struct arch_uprobe *aup= robe, struct insn *insn) } } =20 - auprobe->push.reg_offset =3D reg_offset; - auprobe->push.ilen =3D insn->length; - auprobe->ops =3D &push_xol_ops; + xol->push.reg_offset =3D reg_offset; + xol->push.ilen =3D insn->length; + xol->ops =3D &push_xol_ops; return 0; } =20 @@ -1582,7 +1582,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *aupr= obe, struct mm_struct *mm, if (ret !=3D -ENOSYS) return ret; =20 - ret =3D push_setup_xol_ops(auprobe, &insn); + ret =3D push_setup_xol_ops(&auprobe->xol, &insn); if (ret !=3D -ENOSYS) return ret; =20 @@ -1592,7 +1592,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *aupr= obe, struct mm_struct *mm, */ switch (OPCODE1(&insn)) { case 0x9d: /* popf */ - auprobe->defparam.fixups |=3D UPROBE_FIX_SETF; + auprobe->xol.defparam.fixups |=3D UPROBE_FIX_SETF; break; case 0xc3: /* ret or lret -- ip is correct */ case 0xcb: @@ -1618,10 +1618,10 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *au= probe, struct mm_struct *mm, riprel_analyze(auprobe, &insn); } =20 - auprobe->defparam.ilen =3D insn.length; - auprobe->defparam.fixups |=3D fix_ip_or_call; + auprobe->xol.defparam.ilen =3D insn.length; + auprobe->xol.defparam.fixups |=3D fix_ip_or_call; =20 - auprobe->ops =3D &default_xol_ops; + auprobe->xol.ops =3D &default_xol_ops; return 0; } =20 @@ -1634,8 +1634,8 @@ int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, = struct pt_regs *regs) { struct uprobe_task *utask =3D current->utask; =20 - if (auprobe->ops->pre_xol) { - int err =3D auprobe->ops->pre_xol(auprobe, regs); + if (auprobe->xol.ops->pre_xol) { + int err =3D auprobe->xol.ops->pre_xol(auprobe, regs); if (err) return err; } @@ -1686,8 +1686,8 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe,= struct pt_regs *regs) WARN_ON_ONCE(current->thread.trap_nr !=3D UPROBE_TRAP_NR); current->thread.trap_nr =3D utask->autask.saved_trap_nr; =20 - if (auprobe->ops->post_xol) { - err =3D auprobe->ops->post_xol(auprobe, regs); + if (auprobe->xol.ops->post_xol) { + err =3D auprobe->xol.ops->post_xol(auprobe, regs); if (err) { /* * Restore ->ip for restart or post mortem analysis. @@ -1754,8 +1754,8 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprob= e, struct pt_regs *regs) { struct uprobe_task *utask =3D current->utask; =20 - if (auprobe->ops->abort) - auprobe->ops->abort(auprobe, regs); + if (auprobe->xol.ops->abort) + auprobe->xol.ops->abort(auprobe, regs); =20 current->thread.trap_nr =3D utask->autask.saved_trap_nr; regs->ip =3D utask->vaddr; @@ -1766,8 +1766,8 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprob= e, struct pt_regs *regs) =20 static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) { - if (auprobe->ops->emulate) - return auprobe->ops->emulate(auprobe, regs); + if (auprobe->xol.ops->emulate) + return auprobe->xol.ops->emulate(auprobe, regs); return false; } =20 --=20 2.51.1 From nobody Tue Dec 2 02:52:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7630432E72C; Mon, 17 Nov 2025 12:41:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383293; cv=none; b=iyqsFdDZ7NfWQCumdGE4qf6+G4eREpwP5BvllXMTU4v6AnYmEfGv9cR7QtgLQNpeP6RmaLSG6np3oI+LHQ5QkVTl/s+HSUkVa1EEfBP+hbxJKewtSaktxupJhmJet0rAZWlmMfRS2z/3tGfPXiM6JChPsR524Cmoz6dZZ3CH6pI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383293; c=relaxed/simple; bh=Pc2GqjM7MdxOb7mFpoyfQ0ABTNPxHcevwQvPSUKgUhI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qVl9f7yZuomlBvyvZ/pRPUxxDx9TKxA1DSo3SW16H2PHNjmQqBd8V2ifXK3i9l9XLqXc9j90LiVkR1/gW4DWqZ8FGmu+3relo8RRYwu6qr5c3A55uNdribKbFNMth0cYO8QkCI3rgRq11RSLw/aVsPYxjwE8rv3/aOaz8fauBsA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Jf8DnQek; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Jf8DnQek" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8A681C19421; Mon, 17 Nov 2025 12:41:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763383293; bh=Pc2GqjM7MdxOb7mFpoyfQ0ABTNPxHcevwQvPSUKgUhI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Jf8DnQekLT4UaQQcR6aK3MJ7NRj/Z+9HWHxohGmNBZdhK2MYDsL07DeZAOvgl7siM xXJDie+LqfKek7ZKw2Eu9T+gpXS6k5ZASd2kxSp/3IG7HsDjcws5jLg/IwkuzemCgS jp1k1o7uzGbtkiphUBBFLPEm+PKE9P1oHXclzn3gQNSKZN02Tt3kgovfZDMK8M1xCh QYn7ZBDSWS2WYqa0tkgdwDFpe295V8Mgxjt8kXHyTutZtPr36LIgH37PUxv/BdZ1zz io011Y1NvyTDOJl4KN9uPXLa76zWzkddHNDzJ7Z0vAcFg3D+/FNIIQkiOE0/tu6wF6 W4Q8qWHzbwm7w== From: Jiri Olsa To: Oleg Nesterov , Masami Hiramatsu , Peter Zijlstra , Andrii Nakryiko Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, x86@kernel.org, Song Liu , Yonghong Song , John Fastabend , Steven Rostedt , Ingo Molnar , David Laight Subject: [RFC PATCH 2/8] uprobe/x86: Use struct arch_uprobe_xol in emulate callback Date: Mon, 17 Nov 2025 13:40:51 +0100 Message-ID: <20251117124057.687384-3-jolsa@kernel.org> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117124057.687384-1-jolsa@kernel.org> References: <20251117124057.687384-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Using struct arch_uprobe_xol also in emulate callback which will help in following changes. Signed-off-by: Jiri Olsa --- arch/x86/kernel/uprobes.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index fb9457b29dbc..7d7a5e677472 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -1212,7 +1212,7 @@ static bool can_optimize(struct insn *insn, unsigned = long vaddr) #endif /* CONFIG_X86_64 */ =20 struct uprobe_xol_ops { - bool (*emulate)(struct arch_uprobe *, struct pt_regs *); + bool (*emulate)(struct arch_uprobe*, struct arch_uprobe_xol *, struct pt_= regs *); int (*pre_xol)(struct arch_uprobe *, struct pt_regs *); int (*post_xol)(struct arch_uprobe *, struct pt_regs *); void (*abort)(struct arch_uprobe *, struct pt_regs *); @@ -1291,9 +1291,9 @@ static const struct uprobe_xol_ops default_xol_ops = =3D { .abort =3D default_abort_op, }; =20 -static bool branch_is_call(struct arch_uprobe *auprobe) +static bool branch_is_call(struct arch_uprobe_xol *xol) { - return auprobe->xol.branch.opc1 =3D=3D 0xe8; + return xol->branch.opc1 =3D=3D 0xe8; } =20 #define CASE_COND \ @@ -1325,11 +1325,11 @@ static bool is_cond_jmp_opcode(u8 opcode) } } =20 -static bool check_jmp_cond(struct arch_uprobe *auprobe, struct pt_regs *re= gs) +static bool check_jmp_cond(struct arch_uprobe_xol *xol, struct pt_regs *re= gs) { unsigned long flags =3D regs->flags; =20 - switch (auprobe->xol.branch.opc1) { + switch (xol->branch.opc1) { #define DO(expr) \ return expr; CASE_COND @@ -1344,12 +1344,13 @@ static bool check_jmp_cond(struct arch_uprobe *aupr= obe, struct pt_regs *regs) #undef COND #undef CASE_COND =20 -static bool branch_emulate_op(struct arch_uprobe *auprobe, struct pt_regs = *regs) +static bool branch_emulate_op(struct arch_uprobe *auprobe, struct arch_upr= obe_xol *xol, + struct pt_regs *regs) { - unsigned long new_ip =3D regs->ip +=3D auprobe->xol.branch.ilen; - unsigned long offs =3D (long)auprobe->xol.branch.offs; + unsigned long new_ip =3D regs->ip +=3D xol->branch.ilen; + unsigned long offs =3D (long)xol->branch.offs; =20 - if (branch_is_call(auprobe)) { + if (branch_is_call(xol)) { /* * If it fails we execute this (mangled, see the comment in * branch_clear_offset) insn out-of-line. In the likely case @@ -1361,7 +1362,7 @@ static bool branch_emulate_op(struct arch_uprobe *aup= robe, struct pt_regs *regs) */ if (emulate_push_stack(regs, new_ip)) return false; - } else if (!check_jmp_cond(auprobe, regs)) { + } else if (!check_jmp_cond(xol, regs)) { offs =3D 0; } =20 @@ -1369,19 +1370,20 @@ static bool branch_emulate_op(struct arch_uprobe *a= uprobe, struct pt_regs *regs) return true; } =20 -static bool push_emulate_op(struct arch_uprobe *auprobe, struct pt_regs *r= egs) +static bool push_emulate_op(struct arch_uprobe *auprobe, struct arch_uprob= e_xol *xol, + struct pt_regs *regs) { - unsigned long *src_ptr =3D (void *)regs + auprobe->xol.push.reg_offset; + unsigned long *src_ptr =3D (void *)regs + xol->push.reg_offset; =20 if (emulate_push_stack(regs, *src_ptr)) return false; - regs->ip +=3D auprobe->xol.push.ilen; + regs->ip +=3D xol->push.ilen; return true; } =20 static int branch_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs = *regs) { - BUG_ON(!branch_is_call(auprobe)); + BUG_ON(!branch_is_call(&auprobe->xol)); /* * We can only get here if branch_emulate_op() failed to push the ret * address _and_ another thread expanded our stack before the (mangled) @@ -1767,7 +1769,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprob= e, struct pt_regs *regs) static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) { if (auprobe->xol.ops->emulate) - return auprobe->xol.ops->emulate(auprobe, regs); + return auprobe->xol.ops->emulate(auprobe, &auprobe->xol, regs); return false; } =20 --=20 2.51.1 From nobody Tue Dec 2 02:52:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6D76632E720; Mon, 17 Nov 2025 12:41:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383304; cv=none; b=WxhiR4wgCuMEvcKRr/WdragPkbW0Jod8p2AFlizo356mvT6wTzCCaK33CytZgI/I+dS69qXjUN/JJq/EC2O+zrd2UfqggZ+nkDt37zfJLE5KopVrCQlySevQ826juwcnPjB1RFQyYVCakApIiAvNCHgWXyFcSqqyEXhmlCTw4jE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383304; c=relaxed/simple; bh=EtgjniBI1ey4qVAAv41BTEGXtgpXYBGSNtFMyDswsbg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZPE2JZp2L86CCUOoHTutaHhLdl3XS+csyH4bowbx0wL20L+u+QarGlb1oDT6iEfJYufSVYYZjquMFfEfR2TjWUs3ggoNYL65MWNMB74hL/WkM8sNsGNNPCfZHD+iiElsG0Zek3VOm4kZnGD7+FZA6n8ZyD2lcqwML3VNihLY/oM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MXA6wu5w; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MXA6wu5w" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 998AFC4CEF1; Mon, 17 Nov 2025 12:41:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763383304; bh=EtgjniBI1ey4qVAAv41BTEGXtgpXYBGSNtFMyDswsbg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=MXA6wu5wx2ej8t6FINgPibq+mMXWALYZvYku0YTe4HwG2qlKv/Lo/8XIW8Kvpb0UH xiBvp0q8tHvEGdE+bGEI0KJPl0UPuPIOy8bzVq7ONKaLN7Xml3cHlmGhvnvsZ9+QXV mCwA3RZsYG1zhSUowtWoFoWfLKbtkgZ1B0HwUIPNpgLt5Abvk7VdQ/YEE7aA3kPIjp J3NCl+P6lt17CsOMD4jCRnS/FV0auD16IRpTbscOfmNUQjrQbPmcztrKYhM4jBN+UI T0p4CcPrX5GC6yBwYvmy7jqslB85ulDMdSquVdoodBWHD982zs8r5bRuLNYVeO34WP kuA6IHN+NAZZg== From: Jiri Olsa To: Oleg Nesterov , Masami Hiramatsu , Peter Zijlstra , Andrii Nakryiko Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, x86@kernel.org, Song Liu , Yonghong Song , John Fastabend , Steven Rostedt , Ingo Molnar , David Laight Subject: [RFC PATCH 3/8] uprobe/x86: Add support to emulate mov reg,reg instructions Date: Mon, 17 Nov 2025 13:40:52 +0100 Message-ID: <20251117124057.687384-4-jolsa@kernel.org> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117124057.687384-1-jolsa@kernel.org> References: <20251117124057.687384-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Adding support to emulate mov reg to reg instructions, because it's often part of the function prologue. Signed-off-by: Jiri Olsa --- arch/x86/include/asm/uprobes.h | 5 +++ arch/x86/kernel/uprobes.c | 61 ++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h index 819e35aa61c4..e6fd87a1cbc3 100644 --- a/arch/x86/include/asm/uprobes.h +++ b/arch/x86/include/asm/uprobes.h @@ -44,6 +44,11 @@ struct arch_uprobe_xol { u8 reg_offset; /* to the start of pt_regs */ u8 ilen; } push; + struct { + u16 src; /* to the start of pt_regs */ + u16 dst; /* to the start of pt_regs */ + u8 ilen; + } mov; }; }; =20 diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 7d7a5e677472..5c44c4b84e99 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -19,6 +19,7 @@ #include #include #include +#include =20 /* Post-execution fixups. */ =20 @@ -1414,6 +1415,19 @@ static void branch_clear_offset(struct arch_uprobe *= auprobe, struct insn *insn) 0, insn->immediate.nbytes); } =20 +static bool mov_emulate_op(struct arch_uprobe *auprobe, struct arch_uprobe= _xol *xol, + struct pt_regs *regs) +{ + unsigned long *dst, *src; + + dst =3D (void *) regs + xol->mov.dst; + src =3D (void *) regs + xol->mov.src; + *dst =3D *src; + + regs->ip +=3D xol->mov.ilen; + return true; +} + static const struct uprobe_xol_ops branch_xol_ops =3D { .emulate =3D branch_emulate_op, .post_xol =3D branch_post_xol_op, @@ -1423,6 +1437,10 @@ static const struct uprobe_xol_ops push_xol_ops =3D { .emulate =3D push_emulate_op, }; =20 +static const struct uprobe_xol_ops mov_xol_ops =3D { + .emulate =3D mov_emulate_op, +}; + /* Returns -ENOSYS if branch_xol_ops doesn't handle this insn */ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *= insn) { @@ -1560,6 +1578,45 @@ static int push_setup_xol_ops(struct arch_uprobe_xol= *xol, struct insn *insn) return 0; } =20 +#ifdef CONFIG_X86_64 +/* Returns -ENOSYS if mov_xol_ops doesn't handle this insn */ +static int mov_setup_xol_ops(struct arch_uprobe_xol *xol, struct insn *ins= n) +{ + u8 opc1 =3D OPCODE1(insn); + int off_src, off_dst; + + /* validate opcode */ + if (opc1 !=3D 0x89) + return -ENOSYS; + if (insn->rex_prefix.nbytes !=3D 1 || + insn->rex_prefix.bytes[0] !=3D 0x48) + return -ENOSYS; + + /* only register operands */ + if (X86_MODRM_MOD(insn->modrm.value) !=3D 3) + return -ENOSYS; + + /* get registers offset */ + off_src =3D insn_get_modrm_reg_off(insn); + if (off_src < 0) + return off_src; + off_dst =3D insn_get_modrm_rm_off(insn); + if (off_dst < 0) + return off_dst; + + xol->mov.src =3D off_src; + xol->mov.dst =3D off_dst; + xol->mov.ilen =3D insn->length; + xol->ops =3D &mov_xol_ops; + return 0; +} +#else +static int mov_setup_xol_ops(struct arch_uprobe_xol *xol, struct insn *ins= n) +{ + return -ENOSYS; +} +#endif + /** * arch_uprobe_analyze_insn - instruction analysis including validity and = fixups. * @auprobe: the probepoint information. @@ -1588,6 +1645,10 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *aup= robe, struct mm_struct *mm, if (ret !=3D -ENOSYS) return ret; =20 + ret =3D mov_setup_xol_ops(&auprobe->xol, &insn); + if (ret !=3D -ENOSYS) + return ret; + /* * Figure out which fixups default_post_xol_op() will need to perform, * and annotate defparam->fixups accordingly. --=20 2.51.1 From nobody Tue Dec 2 02:52:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4370B32E12B; Mon, 17 Nov 2025 12:41:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383315; cv=none; b=rIhKVLsEJuBLSXToODLIcrN18dOhDk/Y/7PYWymmbguNNog10E1kVYtXDEoH1Cs3BtTIx2uDEnKgZ7XRvhKa1xfrJFto8F9aY7ikCgW2DjROwf5GIhoLYw5xoHHXFkKZ17M75ucCmLnRsh55u3E4rzhu8oyASv9CrjLTGgPNPgQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383315; c=relaxed/simple; bh=cmWhLOteajP81U9DPJ+I9fRrSgTXE1zBKNwdychnGC0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KYBkHQr2ReB6kMd2vSBSqn7DyXqEIjGybqRgwEkXkpVI31kyZH5PNvHdARNCt3r6wEnzp+XGvxiFl32KpBEMXdQ33eek3CmFGQw9MBlzXgyq40OC1PwFNVSTlWtNKiMVeYp6YeLr0iZvVx2twvKryF28LbZta6Ubj3QOA+Bsar8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=S34H/Dr4; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="S34H/Dr4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5FC1BC2BC86; Mon, 17 Nov 2025 12:41:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763383314; bh=cmWhLOteajP81U9DPJ+I9fRrSgTXE1zBKNwdychnGC0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S34H/Dr4l/HldrRWfxf+yg1T9Y43kGHQ/vFAkAtP/tQmA9N5vBeMlaEe9lcLKt9jQ M80Yi4ZynbSNmvP2dKHvtNqBu31nKWY10NLNwmN84Uv8FSsaSdUuirKrhCMNb130cw hs88Pd5vVmstyUvxGFKuVCp+Lz08IILMT29jZozaHHkW3XSku26Z21HKUzr0chULGb JjK0ikibryIDoYhKrpjx0VF7PcOfuWNWh7HL+FongikgHtYjRR85GgVWg2gNFJkDOw inNl8dDgfbI1WZ7+wackqH7ZoY4/OeXpgSCFBQ/c7WGVna95DHoy19K0bYx5/As3VB CfDGGlCWJpODQ== From: Jiri Olsa To: Oleg Nesterov , Masami Hiramatsu , Peter Zijlstra , Andrii Nakryiko Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, x86@kernel.org, Song Liu , Yonghong Song , John Fastabend , Steven Rostedt , Ingo Molnar , David Laight Subject: [RFC PATCH 4/8] uprobe/x86: Add support to emulate sub imm,reg instructions Date: Mon, 17 Nov 2025 13:40:53 +0100 Message-ID: <20251117124057.687384-5-jolsa@kernel.org> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117124057.687384-1-jolsa@kernel.org> References: <20251117124057.687384-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Adding support to emulate sub reg, imm instructions, because it's often part of the function prologue. Signed-off-by: Jiri Olsa --- arch/x86/include/asm/uprobes.h | 5 +++ arch/x86/kernel/uprobes.c | 73 ++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h index e6fd87a1cbc3..e09aab82b8c1 100644 --- a/arch/x86/include/asm/uprobes.h +++ b/arch/x86/include/asm/uprobes.h @@ -49,6 +49,11 @@ struct arch_uprobe_xol { u16 dst; /* to the start of pt_regs */ u8 ilen; } mov; + struct { + s32 val; + u16 reg; /* to the start of pt_regs */ + u8 ilen; + } sub; }; }; =20 diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 5c44c4b84e99..904c423ea81d 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -1428,6 +1428,40 @@ static bool mov_emulate_op(struct arch_uprobe *aupro= be, struct arch_uprobe_xol * return true; } =20 +#define EFLAGS_MASK (X86_EFLAGS_OF|X86_EFLAGS_SF|X86_EFLAGS_ZF|X86_EFLAGS_= AF|\ + X86_EFLAGS_PF|X86_EFLAGS_CF) + +static bool sub_emulate_op(struct arch_uprobe *auprobe, struct arch_uprobe= _xol *xol, + struct pt_regs *regs) +{ + unsigned long dst, flags =3D regs->flags, val =3D xol->sub.val; + unsigned long *reg =3D (void *) regs + xol->sub.reg; + + dst =3D *reg; + + /* + * Emulate sub with 'sub reg,reg' and get result value and + * flags register change. Not sure it's completely equivalent + * to sub reg,imm so perhaps there's better way. + */ + asm volatile ( + "pushf \n\t" + "push %[flags]; popf \n\t" + "subq %[src], %[dst] \n\t" + "pushf; popq %[flags] \n\t" + "popf \n\t" + : [flags] "+D" (flags), [dst] "+r" (dst) + : [src] "r" (val) + ); + + *reg =3D dst; + regs->flags =3D (regs->flags & ~EFLAGS_MASK) | (flags & EFLAGS_MASK); + regs->ip +=3D xol->sub.ilen; + return true; +} + +#undef EFLAGS_MASK + static const struct uprobe_xol_ops branch_xol_ops =3D { .emulate =3D branch_emulate_op, .post_xol =3D branch_post_xol_op, @@ -1441,6 +1475,10 @@ static const struct uprobe_xol_ops mov_xol_ops =3D { .emulate =3D mov_emulate_op, }; =20 +static const struct uprobe_xol_ops sub_xol_ops =3D { + .emulate =3D sub_emulate_op, +}; + /* Returns -ENOSYS if branch_xol_ops doesn't handle this insn */ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *= insn) { @@ -1610,11 +1648,42 @@ static int mov_setup_xol_ops(struct arch_uprobe_xol= *xol, struct insn *insn) xol->ops =3D &mov_xol_ops; return 0; } + +static int sub_setup_xol_ops(struct arch_uprobe_xol *xol, struct insn *ins= n) +{ + u8 opc1 =3D OPCODE1(insn); + int off; + + if (opc1 !=3D 0x81) + return -ENOSYS; + if (insn->rex_prefix.nbytes !=3D 1 || + insn->rex_prefix.bytes[0] !=3D 0x48) + return -ENOSYS; + if (X86_MODRM_MOD(insn->modrm.value) !=3D 3) + return -ENOSYS; + if (X86_MODRM_REG(insn->modrm.value) !=3D 5) + return -ENOSYS; + + /* get register offset */ + off =3D insn_get_modrm_rm_off(insn); + if (off < 0) + return off; + + xol->sub.reg =3D off; + xol->sub.val =3D insn->immediate.value; + xol->sub.ilen =3D insn->length; + xol->ops =3D &sub_xol_ops; + return 0; +} #else static int mov_setup_xol_ops(struct arch_uprobe_xol *xol, struct insn *ins= n) { return -ENOSYS; } +static int sub_setup_xol_ops(struct arch_uprobe_xol *xol, struct insn *ins= n) +{ + return -ENOSYS; +} #endif =20 /** @@ -1649,6 +1718,10 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *aup= robe, struct mm_struct *mm, if (ret !=3D -ENOSYS) return ret; =20 + ret =3D sub_setup_xol_ops(&auprobe->xol, &insn); + if (ret !=3D -ENOSYS) + return ret; + /* * Figure out which fixups default_post_xol_op() will need to perform, * and annotate defparam->fixups accordingly. --=20 2.51.1 From nobody Tue Dec 2 02:52:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D73632ED22; Mon, 17 Nov 2025 12:42:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383326; cv=none; b=GxeaygP0PtDYANeNYt0Thu0nyjsjuKZ3IIOOVdq1c4f41JDMb1M5RhxR8B7UKXeW0n+djhL+9o7yCTHm4/GUbWwSmXU4sFl7EfbtOYBVtXxW7D1DPMgJ/xTSh2gsnFeHFn6vtLSFs4J1PKKB8Ys71SA7TdXVqZPj0H8IyUNoq64= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383326; c=relaxed/simple; bh=0JwRosMMEiVc+YmndSTGpdLxVuq150xOzaXsDrrF6NM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ivtoPc1Axldb8UmXNPxX+4wFnfSyqjkOQ7NwjNRLorkHTYA2Wd5zfNLU8AyRomCeBue6UAQfDFqxRTkewfpRPF1tP/gNhkoIXu9XuQ/LFj8FmLzQqRRUC1+55d/stoAVIpzZoSTLlWZy8L3+RzPdj0th6hqM7EK38wAPaZToRxw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=I9mfgLS7; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="I9mfgLS7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 57396C113D0; Mon, 17 Nov 2025 12:42:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763383325; bh=0JwRosMMEiVc+YmndSTGpdLxVuq150xOzaXsDrrF6NM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=I9mfgLS7wfC2dMHfs8VjRTiMOJ71iCJetQjJnjlYL/4W+iKnen7Rg1oiK4uCXVKKD TfamWIZ5q9FjilQi2lvClKh2gGiOYWoT1MWhR2AxzJAYaiN7Du7D5GPHSm3yS4LXg4 JKW6mMCZYHWG2RVEBZp7nKk3yH5P20S4aTck11A77J5TgdnYgg5cnO/SKUPRYSAts1 s9wxvW9P0X/dbSISPrrgJ2ILXTYUS6UYh3upaFNJtd3C5DRs95z/dnF8zFLT2dnzN7 hdPw8rOIJRCdLsmRB4cL7DtcBPfedrf8kMD0uH7BqEFutXbDnsDAr70Mlyufy+8rAw WtOQdBcLVTA9A== From: Jiri Olsa To: Oleg Nesterov , Masami Hiramatsu , Peter Zijlstra , Andrii Nakryiko Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, x86@kernel.org, Song Liu , Yonghong Song , John Fastabend , Steven Rostedt , Ingo Molnar , David Laight Subject: [RFC PATCH 5/8] uprobe/x86: Add support to optimize on top of emulated instructions Date: Mon, 17 Nov 2025 13:40:54 +0100 Message-ID: <20251117124057.687384-6-jolsa@kernel.org> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117124057.687384-1-jolsa@kernel.org> References: <20251117124057.687384-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Adding support to optimize uprobe on top of instructions that can be emulated. The idea is to store instructions on underlying 5 bytes and emulate them during the int3 and uprobe syscall execution: - install 'call trampoline' through standard int3 update - if int3 is hit before we finish optimizing we emulate all underlying instructions - when call is installed the uprobe syscall will emulate all underlying instructions Adding opt_xol_ops that emulate instructions that are replaced by 5 bytes call instruction used to optimize the uprobe. Signed-off-by: Jiri Olsa --- arch/x86/include/asm/uprobes.h | 13 ++-- arch/x86/kernel/uprobes.c | 106 ++++++++++++++++++++++++++++++++- include/linux/uprobes.h | 1 + kernel/events/uprobes.c | 6 ++ 4 files changed, 120 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h index e09aab82b8c1..eaa80dc1c836 100644 --- a/arch/x86/include/asm/uprobes.h +++ b/arch/x86/include/asm/uprobes.h @@ -21,8 +21,9 @@ typedef u8 uprobe_opcode_t; #define UPROBE_SWBP_INSN_SIZE 1 =20 enum { - ARCH_UPROBE_FLAG_CAN_OPTIMIZE =3D 0, - ARCH_UPROBE_FLAG_OPTIMIZE_FAIL =3D 1, + ARCH_UPROBE_FLAG_CAN_OPTIMIZE =3D 0, + ARCH_UPROBE_FLAG_OPTIMIZE_FAIL =3D 1, + ARCH_UPROBE_FLAG_OPTIMIZE_EMULATE =3D 2, }; =20 struct uprobe_xol_ops; @@ -59,11 +60,15 @@ struct arch_uprobe_xol { =20 struct arch_uprobe { union { - u8 insn[MAX_UINSN_BYTES]; + u8 insn[5*MAX_UINSN_BYTES]; u8 ixol[MAX_UINSN_BYTES]; }; =20 - struct arch_uprobe_xol xol; + struct arch_uprobe_xol xol; + struct { + struct arch_uprobe_xol xol[5]; + int cnt; + } opt; =20 unsigned long flags; }; diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 904c423ea81d..7f3f537a6425 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -277,13 +277,14 @@ static bool is_prefix_bad(struct insn *insn) return false; } =20 -static int uprobe_init_insn(struct arch_uprobe *auprobe, struct insn *insn= , bool x86_64) +static int uprobe_init_insn_offset(struct arch_uprobe *auprobe, unsigned l= ong offset, + struct insn *insn, bool x86_64) { enum insn_mode m =3D x86_64 ? INSN_MODE_64 : INSN_MODE_32; u32 volatile *good_insns; int ret; =20 - ret =3D insn_decode(insn, auprobe->insn, sizeof(auprobe->insn), m); + ret =3D insn_decode(insn, auprobe->insn + offset, sizeof(auprobe->insn) -= offset, m); if (ret < 0) return -ENOEXEC; =20 @@ -310,6 +311,11 @@ static int uprobe_init_insn(struct arch_uprobe *auprob= e, struct insn *insn, bool return -ENOTSUPP; } =20 +static int uprobe_init_insn(struct arch_uprobe *auprobe, struct insn *insn= , bool x86_64) +{ + return uprobe_init_insn_offset(auprobe, 0, insn, x86_64); +} + #ifdef CONFIG_X86_64 =20 struct uretprobe_syscall_args { @@ -1462,6 +1468,23 @@ static bool sub_emulate_op(struct arch_uprobe *aupro= be, struct arch_uprobe_xol * =20 #undef EFLAGS_MASK =20 +static bool optimized_emulate(struct arch_uprobe *auprobe, struct arch_upr= obe_xol *xol, + struct pt_regs *regs) +{ + int i; + + for (i =3D 0; i < auprobe->opt.cnt; i++) { + WARN_ON(!auprobe->opt.xol[i].ops->emulate(auprobe, &auprobe->opt.xol[i],= regs)); + } + return true; +} + +void arch_uprobe_optimized_emulate(struct arch_uprobe *auprobe, struct pt_= regs *regs) +{ + if (test_bit(ARCH_UPROBE_FLAG_OPTIMIZE_EMULATE, &auprobe->flags)) + optimized_emulate(auprobe, NULL, regs); +} + static const struct uprobe_xol_ops branch_xol_ops =3D { .emulate =3D branch_emulate_op, .post_xol =3D branch_post_xol_op, @@ -1479,6 +1502,10 @@ static const struct uprobe_xol_ops sub_xol_ops =3D { .emulate =3D sub_emulate_op, }; =20 +static const struct uprobe_xol_ops opt_xol_ops =3D { + .emulate =3D optimized_emulate, +}; + /* Returns -ENOSYS if branch_xol_ops doesn't handle this insn */ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *= insn) { @@ -1675,6 +1702,73 @@ static int sub_setup_xol_ops(struct arch_uprobe_xol = *xol, struct insn *insn) xol->ops =3D &sub_xol_ops; return 0; } + +static int opt_setup_xol_insns(struct arch_uprobe *auprobe, struct arch_up= robe_xol *xol, + struct insn *insn) +{ + int ret; + + /* + * TODO somehow separate nop emulation out of branch_xol_ops, + * so we could emulate nop instructions in here. + */ + ret =3D push_setup_xol_ops(xol, insn); + if (ret !=3D -ENOSYS) + return ret; + ret =3D mov_setup_xol_ops(xol, insn); + if (ret !=3D -ENOSYS) + return ret; + ret =3D sub_setup_xol_ops(xol, insn); + if (ret !=3D -ENOSYS) + return ret; + + return -1; +} + +static int opt_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *ins= n) +{ + unsigned long offset =3D insn->length; + struct insn insnX; + int i, ret; + + if (test_bit(ARCH_UPROBE_FLAG_CAN_OPTIMIZE, &auprobe->flags)) + return -ENOSYS; + + ret =3D opt_setup_xol_insns(auprobe, &auprobe->opt.xol[0], insn); + if (ret) + return -ENOSYS; + + auprobe->opt.cnt =3D 1; + if (offset >=3D 5) + goto optimize; + + for (i =3D 1; i < 5; i++) { + ret =3D uprobe_init_insn_offset(auprobe, offset, &insnX, true); + if (ret) + break; + ret =3D opt_setup_xol_insns(auprobe, &auprobe->opt.xol[i], &insnX); + if (ret) + break; + offset +=3D insnX.length; + auprobe->opt.cnt++; + if (offset >=3D 5) + goto optimize; + } + + return -ENOSYS; + +optimize: + set_bit(ARCH_UPROBE_FLAG_CAN_OPTIMIZE, &auprobe->flags); + set_bit(ARCH_UPROBE_FLAG_OPTIMIZE_EMULATE, &auprobe->flags); + auprobe->xol.ops =3D &opt_xol_ops; + + /* + * TODO perhaps we could 'emulate' nop, so there would be no need for + * ARCH_UPROBE_FLAG_OPTIMIZE_EMULATE flag, because we would emulate + * allways. + */ + return 0; +} #else static int mov_setup_xol_ops(struct arch_uprobe_xol *xol, struct insn *ins= n) { @@ -1684,6 +1778,10 @@ static int sub_setup_xol_ops(struct arch_uprobe_xol = *xol, struct insn *insn) { return -ENOSYS; } +static int opt_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *ins= n) +{ + return -ENOSYS; +} #endif =20 /** @@ -1706,6 +1804,10 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *aup= robe, struct mm_struct *mm, if (can_optimize(&insn, addr)) set_bit(ARCH_UPROBE_FLAG_CAN_OPTIMIZE, &auprobe->flags); =20 + ret =3D opt_setup_xol_ops(auprobe, &insn); + if (ret !=3D -ENOSYS) + return ret; + ret =3D branch_setup_xol_ops(auprobe, &insn); if (ret !=3D -ENOSYS) return ret; diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h index ee3d36eda45d..4b9f81ad8316 100644 --- a/include/linux/uprobes.h +++ b/include/linux/uprobes.h @@ -242,6 +242,7 @@ extern void arch_uprobe_clear_state(struct mm_struct *m= m); extern void arch_uprobe_init_state(struct mm_struct *mm); extern void handle_syscall_uprobe(struct pt_regs *regs, unsigned long bp_v= addr); extern void arch_uprobe_optimize(struct arch_uprobe *auprobe, unsigned lon= g vaddr); +extern void arch_uprobe_optimized_emulate(struct arch_uprobe *auprobe, str= uct pt_regs *regs); #else /* !CONFIG_UPROBES */ struct uprobes_state { }; diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index f11ceb8be8c4..dd893030e32e 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -2701,6 +2701,10 @@ void __weak arch_uprobe_optimize(struct arch_uprobe = *auprobe, unsigned long vadd { } =20 +void __weak arch_uprobe_optimized_emulate(struct arch_uprobe *auprobe, str= uct pt_regs *regs) +{ +} + /* * Run handler and ask thread to singlestep. * Ensure all non-fatal signals cannot interrupt thread while it singleste= ps. @@ -2801,6 +2805,8 @@ void handle_syscall_uprobe(struct pt_regs *regs, unsi= gned long bp_vaddr) if (arch_uprobe_ignore(&uprobe->arch, regs)) return; handler_chain(uprobe, regs); + + arch_uprobe_optimized_emulate(&uprobe->arch, regs); } =20 /* --=20 2.51.1 From nobody Tue Dec 2 02:52:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D7DFD331A7D; Mon, 17 Nov 2025 12:42:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383336; cv=none; b=aJZovIw89RNHbnlS6IsaZWQe95FXC36VDGgGWl/SMAR05WzU/RNcgaU3YXcg4GyX9frKV++5ybAblfwrrrmkfYyAuXMF4oDxTGJUXeOhblOh1XRtDIomKvquc+1l+VrOXpDhWdSF18y3N2D2tcNI3wFpoqGJhCM3WADyJ5agnqM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383336; c=relaxed/simple; bh=x6+UjMw+bXbFJFqVCo4FzgPK65NoY/tAW0D2C8W9Rq0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BiawTbPP5zY1BjkxZ+EbcQJDwZ0y/ubfgAR/I6NHQa5tnvEAq+O33arx51Bom6jRlIAcH3JRtBtSavH+sk0O9Ud5kUdUsDgqctjQ4Ozvc/JFI33ghDKuAzlTZ/ak16qlAm5lFrq0Qa3yqVXVYroJ1/5ECT/QTk8SpC+Ool5g1As= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ere/j32l; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ere/j32l" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F3C3BC4CEFB; Mon, 17 Nov 2025 12:42:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763383336; bh=x6+UjMw+bXbFJFqVCo4FzgPK65NoY/tAW0D2C8W9Rq0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ere/j32l6mc/RYI/bbNiqAEQStc6TQs9PA2CuhKAx42TorQ8itmmTC25qMMOhAmpo fS/S48HgnrpIJ5yFtPiIkrIyfwjAh6qr3OCg6k2YeSawZUTdhfk10HTcDTrccEEdp5 S/XwWgJkQ9Ue4DNz30Ecr8k7tha/7y/wULfzctv2Kmr9qZvVs+sqF7kXKDMHLBcgnl EnhlhjOfbulso0PPJy+qvOxxDMFU4myjm0G64aZKo5jpu9F1Ef8jH03qtsWFEFu0MO lD3jRnhAUXnSw6kRhDEukWE0lbYKmIklHzMTBiPEGAwTOfYC1S59wVTTrKPCZtQXFh JE7cxV3P45HCw== From: Jiri Olsa To: Oleg Nesterov , Masami Hiramatsu , Peter Zijlstra , Andrii Nakryiko Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, x86@kernel.org, Song Liu , Yonghong Song , John Fastabend , Steven Rostedt , Ingo Molnar , David Laight Subject: [RFC PATCH 6/8] selftests/bpf: Add test for mov and sub emulation Date: Mon, 17 Nov 2025 13:40:55 +0100 Message-ID: <20251117124057.687384-7-jolsa@kernel.org> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117124057.687384-1-jolsa@kernel.org> References: <20251117124057.687384-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Adding test code for mov and sub instructions emulation. TODO add test for sub flags value emulation. Signed-off-by: Jiri Olsa --- .../selftests/bpf/prog_tests/uprobe_syscall.c | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c b/tool= s/testing/selftests/bpf/prog_tests/uprobe_syscall.c index 955a37751b52..27fa6f309188 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c @@ -765,6 +765,54 @@ static void test_uprobe_error(void) ASSERT_EQ(errno, ENXIO, "errno"); } =20 +__attribute__((aligned(16))) +__nocf_check __weak __naked unsigned long emulate_mov_trigger(void) +{ + asm volatile ( + "pushq %rbp\n" + "movq %rsp,%rbp\n" + "subq $0xb0,%rsp\n" + "addq $0xb0,%rsp\n" + "pop %rbp\n" + "ret\n" + ); +} + +static void test_emulate(void) +{ + struct uprobe_syscall *skel =3D NULL; + unsigned long offset; + + offset =3D get_uprobe_offset(&emulate_mov_trigger); + if (!ASSERT_GE(offset, 0, "get_uprobe_offset")) + return; + + skel =3D uprobe_syscall__open_and_load(); + if (!ASSERT_OK_PTR(skel, "uprobe_syscall__open_and_load")) + goto cleanup; + + /* mov */ + skel->links.probe =3D bpf_program__attach_uprobe_opts(skel->progs.probe, + 0, "/proc/self/exe", offset + 1, NULL); + if (!ASSERT_OK_PTR(skel->links.probe, "bpf_program__attach_uprobe_opts")) + goto cleanup; + + emulate_mov_trigger(); + + bpf_link__destroy(skel->links.probe); + + /* sub */ + skel->links.probe =3D bpf_program__attach_uprobe_opts(skel->progs.probe, + 0, "/proc/self/exe", offset + 4, NULL); + if (!ASSERT_OK_PTR(skel->links.probe, "bpf_program__attach_uprobe_opts")) + goto cleanup; + + emulate_mov_trigger(); + +cleanup: + uprobe_syscall__destroy(skel); +} + static void __test_uprobe_syscall(void) { if (test__start_subtest("uretprobe_regs_equal")) @@ -789,6 +837,8 @@ static void __test_uprobe_syscall(void) test_uprobe_regs_equal(false); if (test__start_subtest("regs_change")) test_regs_change(); + if (test__start_subtest("emulate_mov")) + test_emulate(); } #else static void __test_uprobe_syscall(void) --=20 2.51.1 From nobody Tue Dec 2 02:52:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 73F1F337688; Mon, 17 Nov 2025 12:42:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383347; cv=none; b=NlxteKD1HW3c7r5OeCU+Hnww+oULMeT8O08UfJxA9OykdXYbpU/CEDMMeFdSfnrbCwKq/5f/TC9OBL9dsODPSPnRj26AzQ59NIiOKB/MAgcQ5lSP2QYjsGcSzhxJpj1ePBmlh/JUj84J+iSrWXebv5QrDagXTWuNLdYukMJmjK4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383347; c=relaxed/simple; bh=cE4vQD/v8RCVF+qyXCZu+VSYXoW/3YpROOS/NObDU50=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=huW3Y/Raa0cxawXnxfqXFiP3X2l1lRur4B8zqkyGxJN7Bv5U0HF1lkoH/qrCH6HHry8XFARBmsLJaWjaxMxJsoQp97EvjiTEbAwWNKlNMLy91bR8W5AD216RVlBpfEBIM4gEIL6U8VwQIMp41JszR0gYwBkbjKDcAUlV1EG2BJ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oFll8DXq; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oFll8DXq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9E928C19424; Mon, 17 Nov 2025 12:42:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763383347; bh=cE4vQD/v8RCVF+qyXCZu+VSYXoW/3YpROOS/NObDU50=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=oFll8DXq8tlNWl9wJQCmyvynVkTMO5vBLDzAllNGd/aEu2URZWqxqqQT6dztNbMnA C4XsJ4LgVkQ5A/NlpPnjjZDk/bMXPcn+1xmqLQaZUf+Hdr8wgzuMvs48WstwXmp1eA 1WTuTWNnkdaBe/vl7gjL8PuHeJvtKXB0rs0njPfsoKEe8HuY5ps5NP5WwmCSTShzmX UMGZ65z6W2zI578BpSKIJVIAXAhhrpLUYihJ/WgkXfBY8oFHX89FJHiGJHqU4wrZYF ZDR/VDR7eMZoG4PrxJPYjTUSRjaeryFmYaEmsPJHDB+tphLbvMGbPMavRiJWs6k3cm MtyR2aYt0xJ/g== From: Jiri Olsa To: Oleg Nesterov , Masami Hiramatsu , Peter Zijlstra , Andrii Nakryiko Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, x86@kernel.org, Song Liu , Yonghong Song , John Fastabend , Steven Rostedt , Ingo Molnar , David Laight Subject: [RFC PATCH 7/8] selftests/bpf: Add test for uprobe prologue optimization Date: Mon, 17 Nov 2025 13:40:56 +0100 Message-ID: <20251117124057.687384-8-jolsa@kernel.org> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117124057.687384-1-jolsa@kernel.org> References: <20251117124057.687384-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Adding test that places uprobe on top of supported prologue and checks that the uprobe gets properly optimized. Signed-off-by: Jiri Olsa --- .../selftests/bpf/prog_tests/uprobe_syscall.c | 63 ++++++++++++++++--- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c b/tool= s/testing/selftests/bpf/prog_tests/uprobe_syscall.c index 27fa6f309188..c6a58afc7ace 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c @@ -428,21 +428,21 @@ static void *check_attach(struct uprobe_syscall_execu= ted *skel, trigger_t trigge return tramp; } =20 -static void check_detach(void *addr, void *tramp) +static void check_detach(void *addr, void *tramp, unsigned char *orig) { /* [uprobes_trampoline] stays after detach */ ASSERT_OK(find_uprobes_trampoline(tramp), "uprobes_trampoline"); - ASSERT_OK(memcmp(addr, nop5, 5), "nop5"); + ASSERT_OK(memcmp(addr, orig, 5), "orig"); } =20 static void check(struct uprobe_syscall_executed *skel, struct bpf_link *l= ink, - trigger_t trigger, void *addr, int executed) + trigger_t trigger, void *addr, int executed, unsigned char *orig) { void *tramp; =20 tramp =3D check_attach(skel, trigger, addr, executed); bpf_link__destroy(link); - check_detach(addr, tramp); + check_detach(addr, tramp, orig); } =20 static void test_uprobe_legacy(void) @@ -470,7 +470,7 @@ static void test_uprobe_legacy(void) if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_opts")) goto cleanup; =20 - check(skel, link, uprobe_test, uprobe_test, 2); + check(skel, link, uprobe_test, uprobe_test, 2, nop5); =20 /* uretprobe */ skel->bss->executed =3D 0; @@ -480,7 +480,7 @@ static void test_uprobe_legacy(void) if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_opts")) goto cleanup; =20 - check(skel, link, uprobe_test, uprobe_test, 2); + check(skel, link, uprobe_test, uprobe_test, 2, nop5); =20 cleanup: uprobe_syscall_executed__destroy(skel); @@ -512,7 +512,7 @@ static void test_uprobe_multi(void) if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi")) goto cleanup; =20 - check(skel, link, uprobe_test, uprobe_test, 2); + check(skel, link, uprobe_test, uprobe_test, 2, nop5); =20 /* uretprobe.multi */ skel->bss->executed =3D 0; @@ -522,7 +522,7 @@ static void test_uprobe_multi(void) if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi")) goto cleanup; =20 - check(skel, link, uprobe_test, uprobe_test, 2); + check(skel, link, uprobe_test, uprobe_test, 2, nop5); =20 cleanup: uprobe_syscall_executed__destroy(skel); @@ -555,7 +555,7 @@ static void test_uprobe_session(void) if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi")) goto cleanup; =20 - check(skel, link, uprobe_test, uprobe_test, 4); + check(skel, link, uprobe_test, uprobe_test, 4, nop5); =20 cleanup: uprobe_syscall_executed__destroy(skel); @@ -584,7 +584,7 @@ static void test_uprobe_usdt(void) if (!ASSERT_OK_PTR(link, "bpf_program__attach_usdt")) goto cleanup; =20 - check(skel, link, usdt_test, addr, 2); + check(skel, link, usdt_test, addr, 2, nop5); =20 cleanup: uprobe_syscall_executed__destroy(skel); @@ -813,6 +813,47 @@ static void test_emulate(void) uprobe_syscall__destroy(skel); } =20 +__attribute__((aligned(16))) +__nocf_check __weak __naked void prologue_trigger(void) +{ + asm volatile ( + "pushq %rbp\n" + "movq %rsp,%rbp\n" + "subq $0xb0,%rsp\n" + "addq $0xb0,%rsp\n" + "pop %rbp\n" + "ret\n" + ); +} + +static void test_optimize_prologue(void) +{ + struct uprobe_syscall_executed *skel =3D NULL; + struct bpf_link *link; + unsigned long offset; + + offset =3D get_uprobe_offset(&prologue_trigger); + if (!ASSERT_GE(offset, 0, "get_uprobe_offset")) + goto cleanup; + + /* uprobe */ + skel =3D uprobe_syscall_executed__open_and_load(); + if (!ASSERT_OK_PTR(skel, "uprobe_syscall_executed__open_and_load")) + return; + + skel->bss->pid =3D getpid(); + + link =3D bpf_program__attach_uprobe_opts(skel->progs.test_uprobe, + 0, "/proc/self/exe", offset, NULL); + if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_opts")) + goto cleanup; + + check(skel, link, prologue_trigger, prologue_trigger, 2, (unsigned char *= ) prologue_trigger); + +cleanup: + uprobe_syscall_executed__destroy(skel); +} + static void __test_uprobe_syscall(void) { if (test__start_subtest("uretprobe_regs_equal")) @@ -839,6 +880,8 @@ static void __test_uprobe_syscall(void) test_regs_change(); if (test__start_subtest("emulate_mov")) test_emulate(); + if (test__start_subtest("optimize_prologue")) + test_optimize_prologue(); } #else static void __test_uprobe_syscall(void) --=20 2.51.1 From nobody Tue Dec 2 02:52:36 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2109C3328F3; Mon, 17 Nov 2025 12:42:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383358; cv=none; b=AzsUH0sZVrxZ+Ow2Owj0VlgI2Y9dX+H7PVmj9UGncnbb5ZHxqCWoQA0MKIELq7ft1SFrXrkKXmhw6cwMMkHNGvR8IvNBLQJ4w8oh6PXCVR2+sAppK04H9E7HerNnnIpvJb5TNpuqaQpULfDCiQHFYTq5/5CRXravNWBNRZv2KO8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763383358; c=relaxed/simple; bh=krID4USAu/VFMjYRujB6HjwRNiyiLnLONylIJbyfjr0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nlDmKylOUfkNpAomOPLtksq09ol1zrJQbaf0Mvj5M3nZFpgS6xCNZxDf8Ynzruy8B3QFA5tcmqTw5Fo7OHDLyyjxZXkKQuZlhYVohEcShljkPS8mKyMqQqct8C+ZdPemBzUPC6btgaWnxP3fcUOSJci3YDyn8/9EjenmQb+4gnQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aRY0mm8X; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="aRY0mm8X" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 49E18C4CEFB; Mon, 17 Nov 2025 12:42:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1763383357; bh=krID4USAu/VFMjYRujB6HjwRNiyiLnLONylIJbyfjr0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aRY0mm8X9uQlQN3P2nZoW7GfrzSyqoVX98DyAXdccm0zaLBt7GgoeIK6MRU4lXWzH hIoMEbVIUla1jFR0Ty24KiJmEsQmfIZuw1dyWuu8Mpvpe4WZKPlOQ0x71X3Njaw5U6 9O9XgD7ipljVmNwGG9EUkqe0EQcnPzfMBOOD9PxxRQc9Rp2qW+KMAmlvNj8IQTOYkF vVznioDU0T83XNTJMhLSnJQXpWevrHarPihdVVFnpS3gTDiLsPbnXabZrzI16U6sQk MBaYORnfTVtKpBDgSkiD/PIXHDKUOVcTNHZV6X4If0e21FuF/NUReDL4mg7kvx2Akw xGCMPQDYPVGbA== From: Jiri Olsa To: Oleg Nesterov , Masami Hiramatsu , Peter Zijlstra , Andrii Nakryiko Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, x86@kernel.org, Song Liu , Yonghong Song , John Fastabend , Steven Rostedt , Ingo Molnar , David Laight Subject: [RFC PATCH 8/8] selftests/bpf: Add race test for uprobe proglog optimization Date: Mon, 17 Nov 2025 13:40:57 +0100 Message-ID: <20251117124057.687384-9-jolsa@kernel.org> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20251117124057.687384-1-jolsa@kernel.org> References: <20251117124057.687384-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Adding uprobe race test on top of prologue instructions. Signed-off-by: Jiri Olsa --- .../selftests/bpf/prog_tests/uprobe_syscall.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c b/tool= s/testing/selftests/bpf/prog_tests/uprobe_syscall.c index c6a58afc7ace..8793fbd61ffd 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c @@ -654,10 +654,11 @@ static USDT_DEFINE_SEMA(race); =20 static void *worker_trigger(void *arg) { + trigger_t trigger =3D (trigger_t) arg; unsigned long rounds =3D 0; =20 while (!race_stop) { - uprobe_test(); + trigger(); rounds++; } =20 @@ -667,6 +668,7 @@ static void *worker_trigger(void *arg) =20 static void *worker_attach(void *arg) { + trigger_t trigger =3D (trigger_t) arg; LIBBPF_OPTS(bpf_uprobe_opts, opts); struct uprobe_syscall_executed *skel; unsigned long rounds =3D 0, offset; @@ -677,7 +679,7 @@ static void *worker_attach(void *arg) unsigned long *ref; int err; =20 - offset =3D get_uprobe_offset(&uprobe_test); + offset =3D get_uprobe_offset(trigger); if (!ASSERT_GE(offset, 0, "get_uprobe_offset")) return NULL; =20 @@ -722,7 +724,7 @@ static useconds_t race_msec(void) return 500; } =20 -static void test_uprobe_race(void) +static void test_uprobe_race(trigger_t trigger) { int err, i, nr_threads; pthread_t *threads; @@ -738,7 +740,7 @@ static void test_uprobe_race(void) =20 for (i =3D 0; i < nr_threads; i++) { err =3D pthread_create(&threads[i], NULL, i % 2 ? worker_trigger : worke= r_attach, - NULL); + trigger); if (!ASSERT_OK(err, "pthread_create")) goto cleanup; } @@ -870,8 +872,10 @@ static void __test_uprobe_syscall(void) test_uprobe_session(); if (test__start_subtest("uprobe_usdt")) test_uprobe_usdt(); - if (test__start_subtest("uprobe_race")) - test_uprobe_race(); + if (test__start_subtest("uprobe_race_nop5")) + test_uprobe_race(uprobe_test); + if (test__start_subtest("uprobe_race_prologue")) + test_uprobe_race(prologue_trigger); if (test__start_subtest("uprobe_error")) test_uprobe_error(); if (test__start_subtest("uprobe_regs_equal")) --=20 2.51.1