From: "Chang S. Bae" <chang.seok.bae@intel.com>
To: kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: pbonzini@redhat.com, seanjc@google.com, chao.gao@intel.com,
zhao1.liu@intel.com, chang.seok.bae@intel.com
Subject: [PATCH RFC v1 13/20] KVM: x86: Add REX2 opcode tables to the instruction decoder
Date: Mon, 10 Nov 2025 18:01:24 +0000 [thread overview]
Message-ID: <20251110180131.28264-14-chang.seok.bae@intel.com> (raw)
In-Reply-To: <20251110180131.28264-1-chang.seok.bae@intel.com>
Extend the decoder to find REX2-prefixed opcodes by introducing dedicated
REX2 opcode tables. During initialization, clone the legacy opcode tables
and patch entries that differ under REX2.
Although most REX2-prefixed opcodes follow the legacy tables, some differ
for instructions that do not reference extended register bits or are
newly introduced under REX2. Using separate tables simplifies the
lookup logic and allows efficient patching of exceptions.
The EGPR checker will be implemented later.
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
---
RFC note:
The lookup logic could be separated from the table population, but
keeping the user of the tables close to their initialization helps
clarify the purpose of the new table. If this becomes hard to follow,
splitting the lookup separately can be an option.
---
arch/x86/kvm/emulate.c | 73 +++++++++++++++++++++++++++++++++++++-
arch/x86/kvm/kvm_emulate.h | 2 ++
arch/x86/kvm/x86.c | 1 +
3 files changed, 75 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index ed3a8c0bca20..58879a31abcd 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -4475,6 +4475,19 @@ static const struct opcode opcode_map_0f_38[256] = {
N, N, X4(N), X8(N)
};
+/*
+ * REX2 opcode tables.
+ *
+ * REX2-prefixed opcodes mostly follow the legacy tables but differ slightly
+ * for instructions that do not use R/X/B register bits. Initialize the REX2
+ * tables by copying the legacy ones, then mark mismatched rows as undefined.
+ */
+static struct opcode rex2_opcode_table[256] __ro_after_init;
+static struct opcode rex2_twobyte_table[256] __ro_after_init;
+
+static const struct opcode undefined = D(Undefined);
+static const struct opcode notimpl = N;
+
#undef D
#undef N
#undef G
@@ -4761,6 +4774,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;
@@ -4881,7 +4899,24 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
ctxt->op_bytes = 8;
/* Determine opcode byte(s): */
- if (ctxt->b == 0x0f) {
+ if (ctxt->rex_prefix == REX2_INVALID) {
+ /*
+ * A REX2 prefix was detected, but the prefix decoder
+ * found invalid byte sequence.
+ */
+ opcode = undefined;
+ } else if (ctxt->rex_prefix == REX2_PREFIX) {
+ /* REX2 prefix is only valid when EGPRs are enabled. */
+ if (!emul_egpr_enabled(ctxt)) {
+ opcode = undefined;
+ } else if (ctxt->rex.bits.m0) {
+ ctxt->opcode_len = 2;
+ opcode = rex2_twobyte_table[ctxt->b];
+ } else {
+ ctxt->opcode_len = 1;
+ opcode = rex2_opcode_table[ctxt->b];
+ }
+ } else if (ctxt->b == 0x0f) {
/* Escape byte: start two-byte opcode sequence */
ctxt->b = insn_fetch(u8, ctxt);
if (ctxt->b == 0x38) {
@@ -5526,3 +5561,39 @@ bool emulator_can_use_gpa(struct x86_emulate_ctxt *ctxt)
return true;
}
+
+static void undefine_row(struct opcode *row)
+{
+ struct opcode *ptr = row;
+ int i;
+
+ /* Clear 16 entries per row */
+ for (i = 0; i < 0x10; i++, ptr++)
+ *ptr = undefined;
+}
+
+/*
+ * Populate REX2 opcode table:
+ *
+ * REX2-prefixed opcodes mostly reuse the legacy layout, except for those that
+ * neither reference extended register bits nor are newly introduced under the
+ * REX2 prefix. Initialize both single- and two-byte tables by cloning the
+ * legacy versions, then patch the table for some exceptions.
+ */
+void __init kvm_init_rex2_opcode_table(void)
+{
+ /* Copy legacy tables: */
+ memcpy(rex2_opcode_table, opcode_table, sizeof(opcode_table));
+ memcpy(rex2_twobyte_table, twobyte_table, sizeof(twobyte_table));
+
+ /* Undefine reserved opcode ranges: */
+ undefine_row(&rex2_opcode_table[0x40]);
+ undefine_row(&rex2_opcode_table[0x70]);
+ undefine_row(&rex2_opcode_table[0xa0]);
+ undefine_row(&rex2_opcode_table[0xe0]);
+ undefine_row(&rex2_twobyte_table[0x30]);
+ undefine_row(&rex2_twobyte_table[0x80]);
+
+ /* Mark opcode not yet implemented: */
+ rex2_opcode_table[0xa1] = notimpl;
+}
diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
index b285299ebfa4..cc16211d61f6 100644
--- a/arch/x86/kvm/kvm_emulate.h
+++ b/arch/x86/kvm/kvm_emulate.h
@@ -589,4 +589,6 @@ static inline ulong *reg_rmw(struct x86_emulate_ctxt *ctxt, unsigned nr)
return reg_write(ctxt, nr);
}
+void __init kvm_init_rex2_opcode_table(void);
+
#endif /* _ASM_X86_KVM_X86_EMULATE_H */
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 338986a5a3ae..4c8c2fc3bda6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -14354,6 +14354,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_rmp_fault);
static int __init kvm_x86_init(void)
{
kvm_init_xstate_sizes();
+ kvm_init_rex2_opcode_table();
kvm_mmu_x86_module_init();
mitigate_smt_rsb &= boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible();
--
2.51.0
next prev parent reply other threads:[~2025-11-10 18:24 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 ` Chang S. Bae [this message]
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
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=20251110180131.28264-14-chang.seok.bae@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
all inboxes | Powered by JetHome®