public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: "Chang S. Bae" <chang.seok.bae@intel.com>
To: Paolo Bonzini <pbonzini@redhat.com>, <kvm@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>
Cc: <seanjc@google.com>, <chao.gao@intel.com>, <zhao1.liu@intel.com>
Subject: Re: [PATCH RFC v1 16/20] KVM: x86: Decode REX2 prefix in the emulator
Date: Thu, 13 Nov 2025 15:30:37 -0800	[thread overview]
Message-ID: <25c8c533-73a3-4cc1-9fbf-4301b2155f11@intel.com> (raw)
In-Reply-To: <6a093929-5e35-485a-934c-e0913d14ac14@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 2564 bytes --]

On 11/11/2025 9:55 AM, Paolo Bonzini wrote:
> On 11/10/25 19:01, Chang S. Bae wrote:
>>
>>           case 0x40 ... 0x4f: /* REX */
>>               if (mode != X86EMUL_MODE_PROT64)
>>                   goto done_prefixes;
>> +            if (ctxt->rex_prefix == REX2_PREFIX)
>> +                break;
>>               ctxt->rex_prefix = REX_PREFIX;
>>               ctxt->rex.raw    = 0x0f & ctxt->b;
>>               continue;
>> +        case 0xd5: /* REX2 */
>> +            if (mode != X86EMUL_MODE_PROT64)
>> +                goto done_prefixes;
> Here you should also check
> 
>      if (ctxt->rex_prefix == REX_PREFIX) {
>          ctxt->rex_prefix = REX2_INVALID;
>          goto done_prefixes;
>      }

You're right. Section 3.1.2.1 states:
| A REX prefix (0x4*) immediately preceding the REX2 prefix is not
| allowed and triggers #UD.

Now I think REX2_INVALID would just add another condition to handle
later. Instead, for such invalid case, it might be simpler to mark the
opcode as undefined and jump all the way after the lookup. See the diff
-- please let me know if you dislike it.

>> +            if (ctxt->rex_prefix == REX2_PREFIX &&
>> +                ctxt->rex.bits.m0 == 0)
>> +                break;
>> +            ctxt->rex_prefix = REX2_PREFIX;
>> +            ctxt->rex.raw    = insn_fetch(u8, ctxt);
>> +            continue;
> After REX2 always comes the main opcode byte, so you can "goto 
> done_prefixes" here.  Or even jump here already; in pseudocode:
> 
>      ctxt->b = insn_fetch(u8, ctxt);
>      if (rex2 & REX_M)
>          goto decode_twobyte;
>      else
>          goto decode_onebyte;

Yes, agreed. I think this makes the control flow more explicit.

>> +        if (ctxt->rex_prefix == REX2_PREFIX) {
>> +            /*
>> +             * A legacy or REX prefix following a REX2 prefix
>> +             * forms an invalid byte sequences. Likewise,
>> +             * a second REX2 prefix following a REX2 prefix
>> +             * with M0=0 is invalid.
>> +             */
>> +            ctxt->rex_prefix = REX2_INVALID;
>> +            goto done_prefixes;
>> +        }
> 
> ... and this is not needed.

I really like that this can go away.

[-- Attachment #2: PATCH16.diff --]
[-- Type: text/plain, Size: 2699 bytes --]

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b8a946cbd587..c62d21de14cb 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -4479,6 +4479,8 @@ static const struct opcode opcode_map_0f_38[256] = {
 	N, N, X4(N), X8(N)
 };
 
+static const struct opcode undefined = D(Undefined);
+
 #undef D
 #undef N
 #undef G
@@ -4765,6 +4767,11 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
 	return rc;
 }
 
+static inline bool emul_egpr_enabled(struct x86_emulate_ctxt *ctxt __maybe_unused)
+{
+	return false;
+}
+
 int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int emulation_type)
 {
 	int rc = X86EMUL_CONTINUE;
@@ -4817,7 +4824,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
 	ctxt->op_bytes = def_op_bytes;
 	ctxt->ad_bytes = def_ad_bytes;
 
-	/* Legacy prefixes. */
+	/* Legacy and REX/REX2 prefixes. */
 	for (;;) {
 		switch (ctxt->b = insn_fetch(u8, ctxt)) {
 		case 0x66:	/* operand-size override */
@@ -4860,9 +4867,29 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
 		case 0x40 ... 0x4f: /* REX */
 			if (mode != X86EMUL_MODE_PROT64)
 				goto done_prefixes;
+			if (ctxt->rex_prefix == REX2_PREFIX) {
+				opcode = undefined;
+				goto decode_done;
+			}
 			ctxt->rex_prefix = REX_PREFIX;
 			ctxt->rex        = 0x0f & ctxt->b;
 			continue;
+		case 0xd5: /* REX2 */
+			if (mode != X86EMUL_MODE_PROT64)
+				goto done_prefixes;
+			if ((ctxt->rex_prefix == REX2_PREFIX && (ctxt->rex & REX_M) == 0) ||
+			    (ctxt->rex_prefix == REX_PREFIX) ||
+			    (!emul_egpr_enabled(ctxt))) {
+				opcode = undefined;
+				goto decode_done;
+			}
+			ctxt->rex_prefix = REX2_PREFIX;
+			ctxt->rex = insn_fetch(u8, ctxt);
+			ctxt->b   = insn_fetch(u8, ctxt);
+			if (ctxt->rex & REX_M)
+				goto decode_twobytes;
+			else
+				goto decode_onebyte;
 		case 0xf0:	/* LOCK */
 			ctxt->lock_prefix = 1;
 			break;
@@ -4889,6 +4916,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
 	if (ctxt->b == 0x0f) {
 		/* Escape byte: start two-byte opcode sequence */
 		ctxt->b = insn_fetch(u8, ctxt);
+decode_twobytes:
 		if (ctxt->b == 0x38 && ctxt->rex_prefix != REX2_PREFIX) {
 			/* Three-byte opcode */
 			ctxt->opcode_len = 3;
@@ -4900,10 +4928,12 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
 			opcode = twobyte_table[ctxt->b];
 		}
 	} else {
+decode_onebyte:
 		/* Single-byte opcode */
 		ctxt->opcode_len = 1;
 		opcode = opcode_table[ctxt->b];
 	}
+decode_done:
 	ctxt->d = opcode.flags;
 
 	if (ctxt->d & NoRex2 && ctxt->rex_prefix == REX2_PREFIX)


  reply	other threads:[~2025-11-13 23:30 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-10 18:01 [PATCH RFC v1 00/20] KVM: x86: Support APX feature for guests Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 01/20] KVM: x86: Rename register accessors to be GPR-specific Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 02/20] KVM: x86: Refactor GPR accessors to differentiate register access types Chang S. Bae
2025-11-11 18:08   ` Paolo Bonzini
2025-11-13 23:19     ` Chang S. Bae
2025-11-11 18:11   ` Paolo Bonzini
2025-11-13 23:18     ` Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 03/20] KVM: x86: Implement accessors for extended GPRs Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 04/20] KVM: VMX: Introduce unified instruction info structure Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 05/20] KVM: VMX: Refactor instruction information retrieval Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 06/20] KVM: VMX: Refactor GPR index retrieval from exit qualification Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 07/20] KVM: nVMX: Support the extended instruction info field Chang S. Bae
2025-11-11 17:48   ` Paolo Bonzini
2025-11-12  1:54     ` Chao Gao
2025-11-13 23:21       ` Chang S. Bae
2025-11-17 23:29       ` Paolo Bonzini
2025-11-18  1:39         ` Chao Gao
2025-11-18 10:33           ` Paolo Bonzini
2025-11-13 23:20     ` Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 08/20] KVM: VMX: Support extended register index in exit handling Chang S. Bae
2025-11-11 17:45   ` Paolo Bonzini
2025-11-13 23:22     ` Chang S. Bae
2025-11-13 23:40       ` Paolo Bonzini
2025-11-10 18:01 ` [PATCH RFC v1 09/20] KVM: x86: Support EGPR accessing and tracking for instruction emulation Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 10/20] KVM: x86: Refactor REX prefix handling in " Chang S. Bae
2025-11-11 18:17   ` Paolo Bonzini
2025-11-13 23:23     ` Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 11/20] KVM: x86: Refactor opcode table lookup " Chang S. Bae
2025-11-11 16:55   ` Paolo Bonzini
2025-11-13 23:24     ` Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 12/20] KVM: x86: Support REX2-extended register index in the decoder Chang S. Bae
2025-11-11 16:53   ` Paolo Bonzini
2025-11-13 23:26     ` Chang S. Bae
2025-11-11 16:53   ` Paolo Bonzini
2025-11-10 18:01 ` [PATCH RFC v1 13/20] KVM: x86: Add REX2 opcode tables to the instruction decoder Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 14/20] KVM: x86: Emulate REX2-prefixed 64-bit absolute jump Chang S. Bae
2025-11-11 16:39   ` Paolo Bonzini
2025-11-13 23:27     ` Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 15/20] KVM: x86: Reject EVEX-prefix instructions in the emulator Chang S. Bae
2025-11-11 16:37   ` Paolo Bonzini
2025-11-13 23:28     ` Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 16/20] KVM: x86: Decode REX2 prefix " Chang S. Bae
2025-11-11 17:55   ` Paolo Bonzini
2025-11-13 23:30     ` Chang S. Bae [this message]
2025-11-13 23:34       ` Paolo Bonzini
2025-11-17 20:01       ` Chang S. Bae
2025-11-17 23:33         ` Paolo Bonzini
2025-11-10 18:01 ` [PATCH RFC v1 17/20] KVM: x86: Prepare APX state setting in XCR0 Chang S. Bae
2025-11-11 16:59   ` Paolo Bonzini
2025-11-13 23:32     ` Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 18/20] KVM: x86: Expose APX foundational feature bit to guests Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 19/20] KVM: x86: Expose APX sub-features " Chang S. Bae
2025-11-10 18:01 ` [PATCH RFC v1 20/20] KVM: selftests: Add APX state handling and XCR0 sanity checks Chang S. Bae
2025-11-10 18:50 ` [PATCH RFC v1 00/20] KVM: x86: Support APX feature for guests Chang S. Bae
2025-11-11 18:14 ` Paolo Bonzini

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=25c8c533-73a3-4cc1-9fbf-4301b2155f11@intel.com \
    --to=chang.seok.bae@intel.com \
    --cc=chao.gao@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=zhao1.liu@intel.com \
    /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