Skip to content

Commit 825f0ae

Browse files
ChangSeokBaesean-jc
authored andcommitted
KVM: x86: Refactor REX prefix handling in instruction emulation
Restructure how to represent and interpret REX fields, preparing for handling of both REX2 and VEX. REX uses the upper four bits of a single byte as a fixed identifier, and the lower four bits containing the data. VEX and REX2 extends this so that the first byte identifies the prefix and the rest encode additional bits; and while VEX only has the same four data bits as REX, eight zero bits are a valid value for the data bits of REX2. So, stop storing the REX byte as-is. Instead, store only the low bits of the REX prefix and track separately whether a REX-like prefix was used. No functional changes intended. Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com> Message-ID: <20251110180131.28264-11-chang.seok.bae@intel.com> [Extracted from APX series; removed bitfields and REX2-specific default. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Link: https://patch.msgid.link/20251114003633.60689-9-pbonzini@redhat.com [sean: name REX_{BXRW} enum "rex_bits"] Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 4cb21be commit 825f0ae

File tree

2 files changed

+31
-13
lines changed

2 files changed

+31
-13
lines changed

arch/x86/kvm/emulate.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,13 @@ enum x86_transfer_type {
239239
X86_TRANSFER_TASK_SWITCH,
240240
};
241241

242+
enum rex_bits {
243+
REX_B = 1,
244+
REX_X = 2,
245+
REX_R = 4,
246+
REX_W = 8,
247+
};
248+
242249
static void writeback_registers(struct x86_emulate_ctxt *ctxt)
243250
{
244251
unsigned long dirty = ctxt->regs_dirty;
@@ -919,7 +926,7 @@ static void *decode_register(struct x86_emulate_ctxt *ctxt, u8 modrm_reg,
919926
int byteop)
920927
{
921928
void *p;
922-
int highbyte_regs = (ctxt->rex_prefix == 0) && byteop;
929+
int highbyte_regs = (ctxt->rex_prefix == REX_NONE) && byteop;
923930

924931
if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8)
925932
p = (unsigned char *)reg_rmw(ctxt, modrm_reg & 3) + 1;
@@ -1110,7 +1117,7 @@ static void decode_register_operand(struct x86_emulate_ctxt *ctxt,
11101117
if (ctxt->d & ModRM)
11111118
reg = ctxt->modrm_reg;
11121119
else
1113-
reg = (ctxt->b & 7) | ((ctxt->rex_prefix & 1) << 3);
1120+
reg = (ctxt->b & 7) | (ctxt->rex_bits & REX_B ? 8 : 0);
11141121

11151122
__decode_register_operand(ctxt, op, reg);
11161123
}
@@ -1129,9 +1136,9 @@ static int decode_modrm(struct x86_emulate_ctxt *ctxt,
11291136
int rc = X86EMUL_CONTINUE;
11301137
ulong modrm_ea = 0;
11311138

1132-
ctxt->modrm_reg = ((ctxt->rex_prefix << 1) & 8); /* REX.R */
1133-
index_reg = (ctxt->rex_prefix << 2) & 8; /* REX.X */
1134-
base_reg = (ctxt->rex_prefix << 3) & 8; /* REX.B */
1139+
ctxt->modrm_reg = (ctxt->rex_bits & REX_R ? 8 : 0);
1140+
index_reg = (ctxt->rex_bits & REX_X ? 8 : 0);
1141+
base_reg = (ctxt->rex_bits & REX_B ? 8 : 0);
11351142

11361143
ctxt->modrm_mod = (ctxt->modrm & 0xc0) >> 6;
11371144
ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3;
@@ -2464,7 +2471,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
24642471

24652472
setup_syscalls_segments(&cs, &ss);
24662473

2467-
if ((ctxt->rex_prefix & 0x8) != 0x0)
2474+
if (ctxt->rex_bits & REX_W)
24682475
usermode = X86EMUL_MODE_PROT64;
24692476
else
24702477
usermode = X86EMUL_MODE_PROT32;
@@ -4850,7 +4857,8 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
48504857
case 0x40 ... 0x4f: /* REX */
48514858
if (mode != X86EMUL_MODE_PROT64)
48524859
goto done_prefixes;
4853-
ctxt->rex_prefix = ctxt->b;
4860+
ctxt->rex_prefix = REX_PREFIX;
4861+
ctxt->rex_bits = ctxt->b & 0xf;
48544862
continue;
48554863
case 0xf0: /* LOCK */
48564864
ctxt->lock_prefix = 1;
@@ -4864,15 +4872,15 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
48644872
}
48654873

48664874
/* Any legacy prefix after a REX prefix nullifies its effect. */
4867-
4868-
ctxt->rex_prefix = 0;
4875+
ctxt->rex_prefix = REX_NONE;
4876+
ctxt->rex_bits = 0;
48694877
}
48704878

48714879
done_prefixes:
48724880

48734881
/* REX prefix. */
4874-
if (ctxt->rex_prefix & 8)
4875-
ctxt->op_bytes = 8; /* REX.W */
4882+
if (ctxt->rex_bits & REX_W)
4883+
ctxt->op_bytes = 8;
48764884

48774885
/* Opcode byte(s). */
48784886
if (ctxt->b == 0x0f) {
@@ -5138,7 +5146,8 @@ void init_decode_cache(struct x86_emulate_ctxt *ctxt)
51385146
{
51395147
/* Clear fields that are set conditionally but read without a guard. */
51405148
ctxt->rip_relative = false;
5141-
ctxt->rex_prefix = 0;
5149+
ctxt->rex_prefix = REX_NONE;
5150+
ctxt->rex_bits = 0;
51425151
ctxt->lock_prefix = 0;
51435152
ctxt->op_prefix = false;
51445153
ctxt->rep_prefix = 0;

arch/x86/kvm/kvm_emulate.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,14 @@ typedef void (*fastop_t)(struct fastop *);
319319
#define NR_EMULATOR_GPRS 8
320320
#endif
321321

322+
/*
323+
* Distinguish between no prefix, REX, or in the future REX2.
324+
*/
325+
enum rex_type {
326+
REX_NONE,
327+
REX_PREFIX,
328+
};
329+
322330
struct x86_emulate_ctxt {
323331
void *vcpu;
324332
const struct x86_emulate_ops *ops;
@@ -360,7 +368,8 @@ struct x86_emulate_ctxt {
360368
int (*check_perm)(struct x86_emulate_ctxt *ctxt);
361369

362370
bool rip_relative;
363-
u8 rex_prefix;
371+
enum rex_type rex_prefix;
372+
u8 rex_bits;
364373
u8 lock_prefix;
365374
u8 rep_prefix;
366375
/* bitmaps of registers in _regs[] that can be read */

0 commit comments

Comments
 (0)