From nobody Tue Dec 2 03:00:12 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