* [PATCH 0/3] objtool: Few x86 decoder updates
@ 2025-09-24 13:45 Peter Zijlstra
2025-09-24 13:45 ` [PATCH 1/3] objtool/x86: Remove 0xea hack Peter Zijlstra
` (2 more replies)
0 siblings, 3 replies; 19+ messages in thread
From: Peter Zijlstra @ 2025-09-24 13:45 UTC (permalink / raw)
To: jpoimboe, x86; +Cc: linux-kernel, peterz, alexandre.chartre
Hi,
few patches that update the 0xea/udb situation and fix up the x86_64 NOP
decoding.
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH 1/3] objtool/x86: Remove 0xea hack 2025-09-24 13:45 [PATCH 0/3] objtool: Few x86 decoder updates Peter Zijlstra @ 2025-09-24 13:45 ` 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-24 13:45 ` [PATCH 3/3] objtool/x86: Fix NOP decode Peter Zijlstra 2 siblings, 2 replies; 19+ messages in thread From: Peter Zijlstra @ 2025-09-24 13:45 UTC (permalink / raw) To: jpoimboe, x86; +Cc: linux-kernel, peterz, alexandre.chartre Was properly fixed in the decoder with commit 4b626015e1bf ("x86/insn: Stop decoding i64 instructions in x86-64 mode at opcode") Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- tools/objtool/arch/x86/decode.c | 9 --------- 1 file changed, 9 deletions(-) --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -189,15 +189,6 @@ int arch_decode_instruction(struct objto op2 = ins.opcode.bytes[1]; op3 = ins.opcode.bytes[2]; - /* - * XXX hack, decoder is buggered and thinks 0xea is 7 bytes long. - */ - if (op1 == 0xea) { - insn->len = 1; - insn->type = INSN_BUG; - return 0; - } - if (ins.rex_prefix.nbytes) { rex = ins.rex_prefix.bytes[0]; rex_w = X86_REX_W(rex) >> 3; ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/3] objtool/x86: Remove 0xea hack 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 1 sibling, 0 replies; 19+ messages in thread From: Alexandre Chartre @ 2025-09-25 9:55 UTC (permalink / raw) To: Peter Zijlstra, jpoimboe, x86; +Cc: alexandre.chartre, linux-kernel On 9/24/25 15:45, Peter Zijlstra wrote: > Was properly fixed in the decoder with commit 4b626015e1bf ("x86/insn: > Stop decoding i64 instructions in x86-64 mode at opcode") > > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> > --- > tools/objtool/arch/x86/decode.c | 9 --------- > 1 file changed, 9 deletions(-) > > --- a/tools/objtool/arch/x86/decode.c > +++ b/tools/objtool/arch/x86/decode.c > @@ -189,15 +189,6 @@ int arch_decode_instruction(struct objto > op2 = ins.opcode.bytes[1]; > op3 = ins.opcode.bytes[2]; > > - /* > - * XXX hack, decoder is buggered and thinks 0xea is 7 bytes long. > - */ > - if (op1 == 0xea) { > - insn->len = 1; > - insn->type = INSN_BUG; > - return 0; > - } > - > if (ins.rex_prefix.nbytes) { > rex = ins.rex_prefix.bytes[0]; > rex_w = X86_REX_W(rex) >> 3; > > Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> alex. ^ permalink raw reply [flat|nested] 19+ messages in thread
* [tip: objtool/core] objtool/x86: Remove 0xea hack 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-bot2 for Peter Zijlstra 1 sibling, 0 replies; 19+ messages in thread From: tip-bot2 for Peter Zijlstra @ 2025-10-14 11:47 UTC (permalink / raw) To: linux-tip-commits Cc: Peter Zijlstra (Intel), Alexandre Chartre, x86, linux-kernel The following commit has been merged into the objtool/core branch of tip: Commit-ID: c5df4e1ab8c00c4dc13094fa44e219bc48d910f4 Gitweb: https://git.kernel.org/tip/c5df4e1ab8c00c4dc13094fa44e219bc48d910f4 Author: Peter Zijlstra <peterz@infradead.org> AuthorDate: Wed, 24 Sep 2025 15:22:46 +02:00 Committer: Peter Zijlstra <peterz@infradead.org> CommitterDate: Tue, 14 Oct 2025 13:43:10 +02:00 objtool/x86: Remove 0xea hack Was properly fixed in the decoder with commit 4b626015e1bf ("x86/insn: Stop decoding i64 instructions in x86-64 mode at opcode") Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> --- tools/objtool/arch/x86/decode.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c index 0ad5cc7..ce16fb2 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -189,15 +189,6 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec op2 = ins.opcode.bytes[1]; op3 = ins.opcode.bytes[2]; - /* - * XXX hack, decoder is buggered and thinks 0xea is 7 bytes long. - */ - if (op1 == 0xea) { - insn->len = 1; - insn->type = INSN_BUG; - return 0; - } - if (ins.rex_prefix.nbytes) { rex = ins.rex_prefix.bytes[0]; rex_w = X86_REX_W(rex) >> 3; ^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 2/3] objtool/x86: Add UDB support 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-24 13:45 ` 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 2 siblings, 2 replies; 19+ messages in thread From: Peter Zijlstra @ 2025-09-24 13:45 UTC (permalink / raw) To: jpoimboe, x86; +Cc: linux-kernel, peterz, alexandre.chartre Per commit 85a2d4a890dc ("x86,ibt: Use UDB instead of 0xEA"), make sure objtool also recognises UDB as a #UD instruction. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- tools/objtool/arch/x86/decode.c | 4 ++++ 1 file changed, 4 insertions(+) --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -683,6 +683,10 @@ int arch_decode_instruction(struct objto insn->type = INSN_SYSRET; break; + case 0xd6: /* udb */ + insn->type = INSN_BUG; + break; + case 0xe0: /* loopne */ case 0xe1: /* loope */ case 0xe2: /* loop */ ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 2/3] objtool/x86: Add UDB support 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 1 sibling, 0 replies; 19+ messages in thread From: Alexandre Chartre @ 2025-09-25 9:56 UTC (permalink / raw) To: Peter Zijlstra, jpoimboe, x86; +Cc: alexandre.chartre, linux-kernel On 9/24/25 15:45, Peter Zijlstra wrote: > Per commit 85a2d4a890dc ("x86,ibt: Use UDB instead of 0xEA"), make > sure objtool also recognises UDB as a #UD instruction. > > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> > --- > tools/objtool/arch/x86/decode.c | 4 ++++ > 1 file changed, 4 insertions(+) > > --- a/tools/objtool/arch/x86/decode.c > +++ b/tools/objtool/arch/x86/decode.c > @@ -683,6 +683,10 @@ int arch_decode_instruction(struct objto > insn->type = INSN_SYSRET; > break; > > + case 0xd6: /* udb */ > + insn->type = INSN_BUG; > + break; > + > case 0xe0: /* loopne */ > case 0xe1: /* loope */ > case 0xe2: /* loop */ > > Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> alex. ^ permalink raw reply [flat|nested] 19+ messages in thread
* [tip: objtool/core] objtool/x86: Add UDB support 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-bot2 for Peter Zijlstra 1 sibling, 0 replies; 19+ messages in thread From: tip-bot2 for Peter Zijlstra @ 2025-10-14 11:47 UTC (permalink / raw) To: linux-tip-commits Cc: Peter Zijlstra (Intel), Alexandre Chartre, x86, linux-kernel The following commit has been merged into the objtool/core branch of tip: Commit-ID: 76e1851a1bc28e760d6acc7a54ec9dce05717028 Gitweb: https://git.kernel.org/tip/76e1851a1bc28e760d6acc7a54ec9dce05717028 Author: Peter Zijlstra <peterz@infradead.org> AuthorDate: Wed, 24 Sep 2025 15:25:27 +02:00 Committer: Peter Zijlstra <peterz@infradead.org> CommitterDate: Tue, 14 Oct 2025 13:43:11 +02:00 objtool/x86: Add UDB support Per commit 85a2d4a890dc ("x86,ibt: Use UDB instead of 0xEA"), make sure objtool also recognises UDB as a #UD instruction. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> --- tools/objtool/arch/x86/decode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c index ce16fb2..ef6e96d 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -683,6 +683,10 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec insn->type = INSN_SYSRET; break; + case 0xd6: /* udb */ + insn->type = INSN_BUG; + break; + case 0xe0: /* loopne */ case 0xe1: /* loope */ case 0xe2: /* loop */ ^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 3/3] objtool/x86: Fix NOP decode 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-24 13:45 ` [PATCH 2/3] objtool/x86: Add UDB support Peter Zijlstra @ 2025-09-24 13:45 ` Peter Zijlstra 2025-09-24 17:34 ` Alexandre Chartre 2025-10-14 11:47 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra 2 siblings, 2 replies; 19+ messages in thread From: Peter Zijlstra @ 2025-09-24 13:45 UTC (permalink / raw) To: jpoimboe, x86; +Cc: linux-kernel, peterz, alexandre.chartre For x86_64 the kernel consistently uses 2 instructions for all NOPs: 90 - NOP 0f 1f /0 - NOPL Notably: - REP NOP is PAUSE, not a NOP instruction. - 0f {0c...0f} is reserved space, except for 0f 0d /1, which is PREFETCHW, not a NOP. - 0f {19,1c...1f} is reserved space, except for 0f 1f /0, which is NOPL. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- tools/objtool/arch/x86/decode.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -494,7 +494,8 @@ int arch_decode_instruction(struct objto break; case 0x90: - insn->type = INSN_NOP; + if (prefix != 0xf3) /* REP NOP := PAUSE */ + insn->type = INSN_NOP; break; case 0x9c: @@ -547,13 +548,14 @@ int arch_decode_instruction(struct objto } else if (op2 == 0x0b || op2 == 0xb9) { - /* ud2 */ + /* ud2, ud1 */ insn->type = INSN_BUG; - } else if (op2 == 0x0d || op2 == 0x1f) { + } else if (op2 == 0x1f) { - /* nopl/nopw */ - insn->type = INSN_NOP; + /* 0f 1f /0 := NOPL */ + if (modrm_reg == 0) + insn->type = INSN_NOP; } else if (op2 == 0x1e) { ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 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-10-14 11:47 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra 1 sibling, 1 reply; 19+ messages in thread From: Alexandre Chartre @ 2025-09-24 17:34 UTC (permalink / raw) To: Peter Zijlstra, jpoimboe, x86; +Cc: alexandre.chartre, linux-kernel On 9/24/25 15:45, Peter Zijlstra wrote: > For x86_64 the kernel consistently uses 2 instructions for all NOPs: > > 90 - NOP > 0f 1f /0 - NOPL > > > Notably: > > - REP NOP is PAUSE, not a NOP instruction. > > - 0f {0c...0f} is reserved space, > except for 0f 0d /1, which is PREFETCHW, not a NOP. > > - 0f {19,1c...1f} is reserved space, > except for 0f 1f /0, which is NOPL. > > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> > --- > tools/objtool/arch/x86/decode.c | 12 +++++++----- > 1 file changed, 7 insertions(+), 5 deletions(-) > > --- a/tools/objtool/arch/x86/decode.c > +++ b/tools/objtool/arch/x86/decode.c > @@ -494,7 +494,8 @@ int arch_decode_instruction(struct objto > break; > > case 0x90: > - insn->type = INSN_NOP; > + if (prefix != 0xf3) /* REP NOP := PAUSE */ > + insn->type = INSN_NOP; > break; So this covers NOP1 (0x90) and NOP2 (0x66 0x90), right? > > case 0x9c: > @@ -547,13 +548,14 @@ int arch_decode_instruction(struct objto > > } else if (op2 == 0x0b || op2 == 0xb9) { > > - /* ud2 */ > + /* ud2, ud1 */ > insn->type = INSN_BUG; > > - } else if (op2 == 0x0d || op2 == 0x1f) { > + } else if (op2 == 0x1f) { > > - /* nopl/nopw */ > - insn->type = INSN_NOP; > + /* 0f 1f /0 := NOPL */ > + if (modrm_reg == 0) > + insn->type = INSN_NOP; > > } else if (op2 == 0x1e) { > And this covers all other NOPs (0x0f 0x1f ...), including NOP6 which has a 0x66 preifx (0x66 0xf 0x1f ...) ? From arch/x86/include/asm/nops.h we have: /* * Generic 64bit nops from GAS: * * 1: nop * 2: osp nop * 3: nopl (%eax) * 4: nopl 0x00(%eax) * 5: nopl 0x00(%eax,%eax,1) * 6: osp nopl 0x00(%eax,%eax,1) * 7: nopl 0x00000000(%eax) * 8: nopl 0x00000000(%eax,%eax,1) */ #define BYTES_NOP1 0x90 #define BYTES_NOP2 0x66,BYTES_NOP1 #define BYTES_NOP3 0x0f,0x1f,0x00 #define BYTES_NOP4 0x0f,0x1f,0x40,0x00 #define BYTES_NOP5 0x0f,0x1f,0x44,0x00,0x00 #define BYTES_NOP6 0x66,BYTES_NOP5 #define BYTES_NOP7 0x0f,0x1f,0x80,0x00,0x00,0x00,0x00 #define BYTES_NOP8 0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00 alex. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 2025-09-24 17:34 ` Alexandre Chartre @ 2025-09-24 18:41 ` Peter Zijlstra 2025-09-25 9:55 ` Alexandre Chartre 0 siblings, 1 reply; 19+ messages in thread From: Peter Zijlstra @ 2025-09-24 18:41 UTC (permalink / raw) To: Alexandre Chartre; +Cc: jpoimboe, x86, linux-kernel On Wed, Sep 24, 2025 at 07:34:00PM +0200, Alexandre Chartre wrote: > > On 9/24/25 15:45, Peter Zijlstra wrote: > > For x86_64 the kernel consistently uses 2 instructions for all NOPs: > > > > 90 - NOP > > 0f 1f /0 - NOPL > > > > > > Notably: > > > > - REP NOP is PAUSE, not a NOP instruction. > > > > - 0f {0c...0f} is reserved space, > > except for 0f 0d /1, which is PREFETCHW, not a NOP. > > > > - 0f {19,1c...1f} is reserved space, > > except for 0f 1f /0, which is NOPL. > > > > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> > > --- > > tools/objtool/arch/x86/decode.c | 12 +++++++----- > > 1 file changed, 7 insertions(+), 5 deletions(-) > > > > --- a/tools/objtool/arch/x86/decode.c > > +++ b/tools/objtool/arch/x86/decode.c > > @@ -494,7 +494,8 @@ int arch_decode_instruction(struct objto > > break; > > case 0x90: > > + if (prefix != 0xf3) /* REP NOP := PAUSE */ > > + insn->type = INSN_NOP; > > break; > > So this covers NOP1 (0x90) and NOP2 (0x66 0x90), right? Yes. Everything with opcode 0x90, except 0xf3 0x90, which as stated is PAUSE. > > case 0x9c: > > @@ -547,13 +548,14 @@ int arch_decode_instruction(struct objto > > } else if (op2 == 0x0b || op2 == 0xb9) { > > + /* ud2, ud1 */ > > insn->type = INSN_BUG; > > + } else if (op2 == 0x1f) { > > + /* 0f 1f /0 := NOPL */ > > + if (modrm_reg == 0) > > + insn->type = INSN_NOP; > > } else if (op2 == 0x1e) { > > And this covers all other NOPs (0x0f 0x1f ...), including NOP6 which has > a 0x66 preifx (0x66 0xf 0x1f ...) ? Sorta, it accepts everything with opcode 0f 1f and modrm_reg==0, which is how NOPL is encoded. Both: 66 66 66 66 66 66 66 66 66 66 66 66 66 66 90 (NOP15) And: 66 66 66 66 66 66 66 0f 1f 84 00 00 00 00 00 (NOP15) will be accepted here as max length instructions. The kernel will not actually use those, since a bunch of micro archs have decode penalties for too many prefixes. > From arch/x86/include/asm/nops.h we have: You're looking at old code :-) > /* > * Generic 64bit nops from GAS: > * > * 1: nop > * 2: osp nop > * 3: nopl (%eax) > * 4: nopl 0x00(%eax) > * 5: nopl 0x00(%eax,%eax,1) > * 6: osp nopl 0x00(%eax,%eax,1) > * 7: nopl 0x00000000(%eax) > * 8: nopl 0x00000000(%eax,%eax,1) * 9: cs nopl 0x00000000(%eax,%eax,1) * 10: osp cs nopl 0x00000000(%eax,%eax,1) * 11: osp osp cs nopl 0x00000000(%eax,%eax,1) > */ > #define BYTES_NOP1 0x90 > #define BYTES_NOP2 0x66,BYTES_NOP1 > #define BYTES_NOP3 0x0f,0x1f,0x00 > #define BYTES_NOP4 0x0f,0x1f,0x40,0x00 > #define BYTES_NOP5 0x0f,0x1f,0x44,0x00,0x00 > #define BYTES_NOP6 0x66,BYTES_NOP5 > #define BYTES_NOP7 0x0f,0x1f,0x80,0x00,0x00,0x00,0x00 > #define BYTES_NOP8 0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00 #define BYTES_NOP9 0x2e,BYTES_NOP8 #define BYTES_NOP10 0x66,BYTES_NOP9 #define BYTES_NOP11 0x66,BYTES_NOP10 But yes, first two are NOP and then it switches to NOPL for 3 bytes and longer (2 opcode, 1 modrm). Where for 11 bytes we have: - 3 prefixes - 2 opcode - 1 modrm - 1 sib - 4 displacement ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 2025-09-24 18:41 ` Peter Zijlstra @ 2025-09-25 9:55 ` Alexandre Chartre 2025-09-25 10:03 ` Peter Zijlstra 0 siblings, 1 reply; 19+ messages in thread From: Alexandre Chartre @ 2025-09-25 9:55 UTC (permalink / raw) To: Peter Zijlstra; +Cc: alexandre.chartre, jpoimboe, x86, linux-kernel On 9/24/25 20:41, Peter Zijlstra wrote: > On Wed, Sep 24, 2025 at 07:34:00PM +0200, Alexandre Chartre wrote: >> >> On 9/24/25 15:45, Peter Zijlstra wrote: >>> For x86_64 the kernel consistently uses 2 instructions for all NOPs: >>> >>> 90 - NOP >>> 0f 1f /0 - NOPL >>> >>> >>> Notably: >>> >>> - REP NOP is PAUSE, not a NOP instruction. >>> >>> - 0f {0c...0f} is reserved space, >>> except for 0f 0d /1, which is PREFETCHW, not a NOP. >>> >>> - 0f {19,1c...1f} is reserved space, >>> except for 0f 1f /0, which is NOPL. >>> >>> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> >>> --- >>> tools/objtool/arch/x86/decode.c | 12 +++++++----- >>> 1 file changed, 7 insertions(+), 5 deletions(-) >>> >>> --- a/tools/objtool/arch/x86/decode.c >>> +++ b/tools/objtool/arch/x86/decode.c >>> @@ -494,7 +494,8 @@ int arch_decode_instruction(struct objto >>> break; >>> case 0x90: >>> + if (prefix != 0xf3) /* REP NOP := PAUSE */ >>> + insn->type = INSN_NOP; >>> break; >> >> So this covers NOP1 (0x90) and NOP2 (0x66 0x90), right? > > Yes. Everything with opcode 0x90, except 0xf3 0x90, which as stated is > PAUSE. > What about 0x49 0x90, which is xchg (XCHG r8,rAX) ? >>> case 0x9c: >>> @@ -547,13 +548,14 @@ int arch_decode_instruction(struct objto >>> } else if (op2 == 0x0b || op2 == 0xb9) { >>> + /* ud2, ud1 */ >>> insn->type = INSN_BUG; >>> + } else if (op2 == 0x1f) { >>> + /* 0f 1f /0 := NOPL */ >>> + if (modrm_reg == 0) >>> + insn->type = INSN_NOP; >>> } else if (op2 == 0x1e) { >> >> And this covers all other NOPs (0x0f 0x1f ...), including NOP6 which has >> a 0x66 preifx (0x66 0xf 0x1f ...) ? > > Sorta, it accepts everything with opcode 0f 1f and modrm_reg==0, which is > how NOPL is encoded. > > Both: 66 66 66 66 66 66 66 66 66 66 66 66 66 66 90 (NOP15) > And: 66 66 66 66 66 66 66 0f 1f 84 00 00 00 00 00 (NOP15) > > will be accepted here as max length instructions. The kernel will not > actually use those, since a bunch of micro archs have decode penalties > for too many prefixes. > >> From arch/x86/include/asm/nops.h we have: > > You're looking at old code :-) > Correct, I was on the 5.15 branch. alex. >> /* >> * Generic 64bit nops from GAS: >> * >> * 1: nop >> * 2: osp nop >> * 3: nopl (%eax) >> * 4: nopl 0x00(%eax) >> * 5: nopl 0x00(%eax,%eax,1) >> * 6: osp nopl 0x00(%eax,%eax,1) >> * 7: nopl 0x00000000(%eax) >> * 8: nopl 0x00000000(%eax,%eax,1) > > * 9: cs nopl 0x00000000(%eax,%eax,1) > * 10: osp cs nopl 0x00000000(%eax,%eax,1) > * 11: osp osp cs nopl 0x00000000(%eax,%eax,1) > >> */ >> #define BYTES_NOP1 0x90 >> #define BYTES_NOP2 0x66,BYTES_NOP1 >> #define BYTES_NOP3 0x0f,0x1f,0x00 >> #define BYTES_NOP4 0x0f,0x1f,0x40,0x00 >> #define BYTES_NOP5 0x0f,0x1f,0x44,0x00,0x00 >> #define BYTES_NOP6 0x66,BYTES_NOP5 >> #define BYTES_NOP7 0x0f,0x1f,0x80,0x00,0x00,0x00,0x00 >> #define BYTES_NOP8 0x0f,0x1f,0x84,0x00,0x00,0x00,0x00,0x00 > > #define BYTES_NOP9 0x2e,BYTES_NOP8 > #define BYTES_NOP10 0x66,BYTES_NOP9 > #define BYTES_NOP11 0x66,BYTES_NOP10 > > But yes, first two are NOP and then it switches to NOPL for 3 bytes and > longer (2 opcode, 1 modrm). Where for 11 bytes we have: > > - 3 prefixes > - 2 opcode > - 1 modrm > - 1 sib > - 4 displacement > ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 2025-09-25 9:55 ` Alexandre Chartre @ 2025-09-25 10:03 ` Peter Zijlstra 2025-09-25 10:42 ` Peter Zijlstra 0 siblings, 1 reply; 19+ messages in thread From: Peter Zijlstra @ 2025-09-25 10:03 UTC (permalink / raw) To: Alexandre Chartre; +Cc: jpoimboe, x86, linux-kernel On Thu, Sep 25, 2025 at 11:55:23AM +0200, Alexandre Chartre wrote: > > On 9/24/25 20:41, Peter Zijlstra wrote: > > On Wed, Sep 24, 2025 at 07:34:00PM +0200, Alexandre Chartre wrote: > > > > > > On 9/24/25 15:45, Peter Zijlstra wrote: > > > > For x86_64 the kernel consistently uses 2 instructions for all NOPs: > > > > > > > > 90 - NOP > > > > 0f 1f /0 - NOPL > > > > > > > > > > > > Notably: > > > > > > > > - REP NOP is PAUSE, not a NOP instruction. > > > > > > > > - 0f {0c...0f} is reserved space, > > > > except for 0f 0d /1, which is PREFETCHW, not a NOP. > > > > > > > > - 0f {19,1c...1f} is reserved space, > > > > except for 0f 1f /0, which is NOPL. > > > > > > > > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> > > > > --- > > > > tools/objtool/arch/x86/decode.c | 12 +++++++----- > > > > 1 file changed, 7 insertions(+), 5 deletions(-) > > > > > > > > --- a/tools/objtool/arch/x86/decode.c > > > > +++ b/tools/objtool/arch/x86/decode.c > > > > @@ -494,7 +494,8 @@ int arch_decode_instruction(struct objto > > > > break; > > > > case 0x90: > > > > + if (prefix != 0xf3) /* REP NOP := PAUSE */ > > > > + insn->type = INSN_NOP; > > > > break; > > > > > > So this covers NOP1 (0x90) and NOP2 (0x66 0x90), right? > > > > Yes. Everything with opcode 0x90, except 0xf3 0x90, which as stated is > > PAUSE. > > > > What about 0x49 0x90, which is xchg (XCHG r8,rAX) ? Ooh, that is a nice one. Yes, that needs fixing. Thanks! ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 2025-09-25 10:03 ` Peter Zijlstra @ 2025-09-25 10:42 ` Peter Zijlstra 2025-09-25 11:29 ` Andrew Cooper 2025-09-25 13:05 ` Alexandre Chartre 0 siblings, 2 replies; 19+ messages in thread From: Peter Zijlstra @ 2025-09-25 10:42 UTC (permalink / raw) To: Alexandre Chartre; +Cc: jpoimboe, x86, linux-kernel On Thu, Sep 25, 2025 at 12:03:23PM +0200, Peter Zijlstra wrote: > > > > > case 0x90: > > > > > + if (prefix != 0xf3) /* REP NOP := PAUSE */ > > > > > + insn->type = INSN_NOP; > > > > > break; > > What about 0x49 0x90, which is xchg (XCHG r8,rAX) ? I've made that: case 0x90: if (rex_b) /* XCHG %r8, %rax */ break; if (prefix == 0xf3) /* REP NOP := PAUSE */ break; insn->type = INSN_NOP; break; ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 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:05 ` Alexandre Chartre 1 sibling, 1 reply; 19+ messages in thread From: Andrew Cooper @ 2025-09-25 11:29 UTC (permalink / raw) To: peterz; +Cc: alexandre.chartre, jpoimboe, linux-kernel, x86 > I've made that: > > case 0x90: > if (rex_b) /* XCHG %r8, %rax */ > break; > > if (prefix == 0xf3) /* REP NOP := PAUSE */ > break; > > insn->type = INSN_NOP; > break; Legacy prefixes can come in any order. What is F3 66 90 ? Also, VEX/EVEX/REX2 want excluding too, all of which can encode rex_b differently. Is it really only rex_b which prevents NOP becoming a pause, or is it any REX prefix? I would have thought it was any REX prefix. ~Andrew ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 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 0 siblings, 2 replies; 19+ messages in thread From: Peter Zijlstra @ 2025-09-25 12:43 UTC (permalink / raw) To: Andrew Cooper; +Cc: alexandre.chartre, jpoimboe, linux-kernel, x86 On Thu, Sep 25, 2025 at 12:29:18PM +0100, Andrew Cooper wrote: > > I've made that: > > > > case 0x90: > > if (rex_b) /* XCHG %r8, %rax */ > > break; > > > > if (prefix == 0xf3) /* REP NOP := PAUSE */ > > break; > > > > insn->type = INSN_NOP; > > break; > > Legacy prefixes can come in any order. What is F3 66 90 ? > > Also, VEX/EVEX/REX2 want excluding too, all of which can encode rex_b > differently. So luckily objtool only really cares about instructions as found in the kernel text. Neither f3 66 90 nor VEX/EVEX/REX2 prefixes are of much concern. 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 :/ > Is it really only rex_b which prevents NOP becoming a pause, or is it > any REX prefix? I would have thought it was any REX prefix. SDM opcode table and instruction reference seems consistent with f3 only. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 2025-09-25 12:43 ` Peter Zijlstra @ 2025-09-25 13:04 ` Alexandre Chartre 2025-09-25 14:11 ` Peter Zijlstra 1 sibling, 0 replies; 19+ messages in thread From: Alexandre Chartre @ 2025-09-25 13:04 UTC (permalink / raw) To: Peter Zijlstra, Andrew Cooper Cc: alexandre.chartre, jpoimboe, linux-kernel, x86 On 9/25/25 14:43, Peter Zijlstra wrote: > On Thu, Sep 25, 2025 at 12:29:18PM +0100, Andrew Cooper wrote: >>> I've made that: >>> >>> case 0x90: >>> if (rex_b) /* XCHG %r8, %rax */ >>> break; >>> >>> if (prefix == 0xf3) /* REP NOP := PAUSE */ >>> break; >>> >>> insn->type = INSN_NOP; >>> break; >> >> Legacy prefixes can come in any order. What is F3 66 90 ? >> >> Also, VEX/EVEX/REX2 want excluding too, all of which can encode rex_b >> differently. > > So luckily objtool only really cares about instructions as found in the > kernel text. Neither f3 66 90 nor VEX/EVEX/REX2 prefixes are of much > concern. And it looks like objtool ignores VEX instructions earlier in the same function: int arch_decode_instruction(struct objtool_file *file, const struct section *sec, unsigned long offset, unsigned int maxlen, struct instruction *insn) { ... if (ins.vex_prefix.nbytes) return 0; ... } vex_prefix is set for VEX/EVEX/VEX3/VEX2. alex. > 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 :/ > >> Is it really only rex_b which prevents NOP becoming a pause, or is it >> any REX prefix? I would have thought it was any REX prefix. > > SDM opcode table and instruction reference seems consistent with f3 > only. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 2025-09-25 12:43 ` Peter Zijlstra 2025-09-25 13:04 ` Alexandre Chartre @ 2025-09-25 14:11 ` Peter Zijlstra 1 sibling, 0 replies; 19+ messages in thread From: Peter Zijlstra @ 2025-09-25 14:11 UTC (permalink / raw) To: Andrew Cooper; +Cc: alexandre.chartre, jpoimboe, linux-kernel, x86 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) { ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 3/3] objtool/x86: Fix NOP decode 2025-09-25 10:42 ` Peter Zijlstra 2025-09-25 11:29 ` Andrew Cooper @ 2025-09-25 13:05 ` Alexandre Chartre 1 sibling, 0 replies; 19+ messages in thread From: Alexandre Chartre @ 2025-09-25 13:05 UTC (permalink / raw) To: Peter Zijlstra; +Cc: alexandre.chartre, jpoimboe, x86, linux-kernel On 9/25/25 12:42, Peter Zijlstra wrote: > On Thu, Sep 25, 2025 at 12:03:23PM +0200, Peter Zijlstra wrote: > >>>>>> case 0x90: >>>>>> + if (prefix != 0xf3) /* REP NOP := PAUSE */ >>>>>> + insn->type = INSN_NOP; >>>>>> break; > >>> What about 0x49 0x90, which is xchg (XCHG r8,rAX) ? > > I've made that: > > case 0x90: > if (rex_b) /* XCHG %r8, %rax */ > break; > > if (prefix == 0xf3) /* REP NOP := PAUSE */ > break; > > insn->type = INSN_NOP; > break; > > Sounds good. Reviewed-by: Alexandre Chartre <alexandre.chartre@oracle.com> alex. ^ permalink raw reply [flat|nested] 19+ messages in thread
* [tip: objtool/core] objtool/x86: Fix NOP decode 2025-09-24 13:45 ` [PATCH 3/3] objtool/x86: Fix NOP decode Peter Zijlstra 2025-09-24 17:34 ` Alexandre Chartre @ 2025-10-14 11:47 ` tip-bot2 for Peter Zijlstra 1 sibling, 0 replies; 19+ messages in thread From: tip-bot2 for Peter Zijlstra @ 2025-10-14 11:47 UTC (permalink / raw) To: linux-tip-commits; +Cc: Peter Zijlstra (Intel), x86, linux-kernel The following commit has been merged into the objtool/core branch of tip: Commit-ID: 044f721ccd33103349eebbb960825584bc6d8e23 Gitweb: https://git.kernel.org/tip/044f721ccd33103349eebbb960825584bc6d8e23 Author: Peter Zijlstra <peterz@infradead.org> AuthorDate: Wed, 24 Sep 2025 15:27:03 +02:00 Committer: Peter Zijlstra <peterz@infradead.org> CommitterDate: Tue, 14 Oct 2025 13:43:11 +02:00 objtool/x86: Fix NOP decode For x86_64 the kernel consistently uses 2 instructions for all NOPs: 90 - NOP 0f 1f /0 - NOPL Notably: - REP NOP is PAUSE, not a NOP instruction. - 0f {0c...0f} is reserved space, except for 0f 0d /1, which is PREFETCHW, not a NOP. - 0f {19,1c...1f} is reserved space, except for 0f 1f /0, which is NOPL. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> --- tools/objtool/arch/x86/decode.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c index ef6e96d..204e2ad 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c @@ -494,6 +494,12 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec break; case 0x90: + if (rex_b) /* XCHG %r8, %rax */ + break; + + if (prefix == 0xf3) /* REP NOP := PAUSE */ + break; + insn->type = INSN_NOP; break; @@ -547,13 +553,14 @@ int arch_decode_instruction(struct objtool_file *file, const struct section *sec } else if (op2 == 0x0b || op2 == 0xb9) { - /* ud2 */ + /* ud2, ud1 */ insn->type = INSN_BUG; - } else if (op2 == 0x0d || op2 == 0x1f) { + } else if (op2 == 0x1f) { - /* nopl/nopw */ - insn->type = INSN_NOP; + /* 0f 1f /0 := NOPL */ + if (modrm_reg == 0) + insn->type = INSN_NOP; } else if (op2 == 0x1e) { ^ permalink raw reply related [flat|nested] 19+ messages in thread
end of thread, other threads:[~2025-10-14 11:48 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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 2025-09-25 13:05 ` Alexandre Chartre 2025-10-14 11:47 ` [tip: objtool/core] " tip-bot2 for Peter Zijlstra
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox