public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: alexandre.chartre@oracle.com, jpoimboe@kernel.org,
	linux-kernel@vger.kernel.org, x86@kernel.org
Subject: Re: [PATCH 3/3] objtool/x86: Fix NOP decode
Date: Thu, 25 Sep 2025 16:11:47 +0200	[thread overview]
Message-ID: <20250925141147.GA4068168@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <20250925124332.GA3245006@noisy.programming.kicks-ass.net>

On Thu, Sep 25, 2025 at 02:43:32PM +0200, Peter Zijlstra wrote:

> But yes.. I happen to have an insn_is_nop() function that can be used on
> userspace, and that certainly wants to be taught about these... x86 is
> such a pain :/

This is the delta I ended up with for my insn_is_nop() function to
support *VEX*/REX2.

I'll post the whole thing later.

--- a/arch/x86/include/asm/insn.h
+++ b/arch/x86/include/asm/insn.h
@@ -138,6 +138,10 @@ struct insn {
 #define X86_VEX_V(vex)	(((vex) & 0x78) >> 3)	/* VEX3 Byte2, VEX2 Byte1 */
 #define X86_VEX_P(vex)	((vex) & 0x03)		/* VEX3 Byte2, VEX2 Byte1 */
 #define X86_VEX_M_MAX	0x1f			/* VEX3.M Maximum value */
+/* EVEX bit fields */
+#define X86_EVEX_R4(vex) ((vex) & 0x10)		/* EVEX Byte1 */
+#define X86_EVEX_B4(vex) ((vex) & 0x08)		/* EVEX Byte1 */
+#define X86_EVEX_X4(vex) ((vex) & 0x04)		/* EVEX Byte2 */
 /* XOP bit fields */
 #define X86_XOP_R(xop)	((xop) & 0x80)	/* XOP Byte2 */
 #define X86_XOP_X(xop)	((xop) & 0x40)	/* XOP Byte2 */
--- a/arch/x86/lib/insn-eval.c
+++ b/arch/x86/lib/insn-eval.c
@@ -1689,33 +1689,62 @@ enum insn_mmio_type insn_decode_mmio(str
  */
 bool insn_is_nop(struct insn *insn)
 {
-	u8 rex, rex_b = 0, rex_x = 0, rex_r = 0, rex_w = 0;
+	u8 b3 = 0, x3 = 0, r3 = 0, w = 0;
+	u8 b4 = 0, x4 = 0, r4 = 0;
 	u8 modrm, modrm_mod, modrm_reg, modrm_rm;
 	u8 sib = 0, sib_scale, sib_index, sib_base;
 	insn_byte_t p;
+	u8 nrex, rex;
 	int i;
 
-	if (insn->rex_prefix.nbytes) {
-		rex = insn->rex_prefix.bytes[0];
-		rex_w = !!X86_REX_W(rex);
-		rex_r = !!X86_REX_R(rex);
-		rex_x = !!X86_REX_X(rex);
-		rex_b = !!X86_REX_B(rex);
+	if ((nrex = insn->rex_prefix.nbytes)) {
+		rex = insn->rex_prefix.bytes[nrex-1];
+
+		w  = !!X86_REX_W(rex);
+		r3 = !!X86_REX_R(rex);
+		x3 = !!X86_REX_X(rex);
+		b3 = !!X86_REX_B(rex);
+		if (nrex > 1) {
+			r4 = !!X86_REX2_R(rex);
+			x4 = !!X86_REX2_X(rex);
+			b4 = !!X86_REX2_B(rex);
+		}
+
+	} else switch (insn->vex_prefix.nbytes) {
+	case 2: /* VEX2 */
+		r3 =  !X86_VEX_R(insn->vex_prefix.bytes[1]);
+		break;
+	case 3: /* VEX3 */
+		r3 =  !X86_VEX_R(insn->vex_prefix.bytes[1]);
+		x3 =  !X86_VEX_X(insn->vex_prefix.bytes[1]);
+		b3 =  !X86_VEX_B(insn->vex_prefix.bytes[1]);
+		w  = !!X86_VEX_W(insn->vex_prefix.bytes[2]);
+		break;
+	case 4: /* EVEX */
+		r3 =  !X86_VEX_R(insn->vex_prefix.bytes[1]);
+		x3 =  !X86_VEX_X(insn->vex_prefix.bytes[1]);
+		b3 =  !X86_VEX_B(insn->vex_prefix.bytes[1]);
+		w  = !!X86_VEX_W(insn->vex_prefix.bytes[2]);
+		r4 =  !X86_EVEX_R4(insn->vex_prefix.bytes[1]);
+		b4 = !!X86_EVEX_B4(insn->vex_prefix.bytes[1]);
+		x4 =  !X86_EVEX_X4(insn->vex_prefix.bytes[2]);
+		break;
+	default: break;
 	}
 
 	if (insn->modrm.nbytes) {
 		modrm = insn->modrm.bytes[0];
 		modrm_mod = X86_MODRM_MOD(modrm);
-		modrm_reg = X86_MODRM_REG(modrm) + 8*rex_r;
-		modrm_rm  = X86_MODRM_RM(modrm)  + 8*rex_b;
+		modrm_reg = X86_MODRM_REG(modrm) + 8*r3 + 16*r4;
+		modrm_rm  = X86_MODRM_RM(modrm)  + 8*b3 + 16*b4;
 		modrm = 1;
 	}
 
 	if (insn->sib.nbytes) {
 		sib = insn->sib.bytes[0];
 		sib_scale = X86_SIB_SCALE(sib);
-		sib_index = X86_SIB_INDEX(sib) + 8*rex_x;
-		sib_base  = X86_SIB_BASE(sib)  + 8*rex_b;
+		sib_index = X86_SIB_INDEX(sib) + 8*x3 + 16*x4;
+		sib_base  = X86_SIB_BASE(sib)  + 8*b3 + 16*b4;
 		sib = 1;
 
 		modrm_rm = sib_base;
@@ -1729,7 +1758,7 @@ bool insn_is_nop(struct insn *insn)
 		if (modrm_mod != 3) /* register-direct */
 			return false;
 
-		if (insn->x86_64 && !rex_w) /* native size */
+		if (insn->x86_64 && !w) /* native size */
 			return false;
 
 		for_each_insn_prefix(insn, i, p) {
@@ -1743,7 +1772,7 @@ bool insn_is_nop(struct insn *insn)
 		if (modrm_mod == 0 || modrm_mod == 3) /* register-indirect with disp */
 			return false;
 
-		if (insn->x86_64 && !rex_w) /* native size */
+		if (insn->x86_64 && !w) /* native size */
 			return false;
 
 		if (insn->displacement.value != 0)
@@ -1760,7 +1789,7 @@ bool insn_is_nop(struct insn *insn)
 		return modrm_reg == modrm_rm; /* LEA 0(%reg), %reg */
 
 	case 0x90: /* NOP */
-		if (rex_b) /* XCHG %r8,%rax */
+		if (b3 || b4) /* XCHG %r8,%rax */
 			return false;
 
 		for_each_insn_prefix(insn, i, p) {

  parent reply	other threads:[~2025-09-25 14:11 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-24 13:45 [PATCH 0/3] objtool: Few x86 decoder updates Peter Zijlstra
2025-09-24 13:45 ` [PATCH 1/3] objtool/x86: Remove 0xea hack Peter Zijlstra
2025-09-25  9:55   ` Alexandre Chartre
2025-10-14 11:47   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2025-09-24 13:45 ` [PATCH 2/3] objtool/x86: Add UDB support Peter Zijlstra
2025-09-25  9:56   ` Alexandre Chartre
2025-10-14 11:47   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
2025-09-24 13:45 ` [PATCH 3/3] objtool/x86: Fix NOP decode Peter Zijlstra
2025-09-24 17:34   ` Alexandre Chartre
2025-09-24 18:41     ` Peter Zijlstra
2025-09-25  9:55       ` Alexandre Chartre
2025-09-25 10:03         ` Peter Zijlstra
2025-09-25 10:42           ` Peter Zijlstra
2025-09-25 11:29             ` Andrew Cooper
2025-09-25 12:43               ` Peter Zijlstra
2025-09-25 13:04                 ` Alexandre Chartre
2025-09-25 14:11                 ` Peter Zijlstra [this message]
2025-09-25 13:05             ` Alexandre Chartre
2025-10-14 11:47   ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250925141147.GA4068168@noisy.programming.kicks-ass.net \
    --to=peterz@infradead.org \
    --cc=alexandre.chartre@oracle.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=jpoimboe@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox