Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Chang S. Bae and committed by
Sean Christopherson
825f0aec 4cb21be4

+31 -13
+21 -12
arch/x86/kvm/emulate.c
··· 239 239 X86_TRANSFER_TASK_SWITCH, 240 240 }; 241 241 242 + enum rex_bits { 243 + REX_B = 1, 244 + REX_X = 2, 245 + REX_R = 4, 246 + REX_W = 8, 247 + }; 248 + 242 249 static void writeback_registers(struct x86_emulate_ctxt *ctxt) 243 250 { 244 251 unsigned long dirty = ctxt->regs_dirty; ··· 926 919 int byteop) 927 920 { 928 921 void *p; 929 - int highbyte_regs = (ctxt->rex_prefix == 0) && byteop; 922 + int highbyte_regs = (ctxt->rex_prefix == REX_NONE) && byteop; 930 923 931 924 if (highbyte_regs && modrm_reg >= 4 && modrm_reg < 8) 932 925 p = (unsigned char *)reg_rmw(ctxt, modrm_reg & 3) + 1; ··· 1117 1110 if (ctxt->d & ModRM) 1118 1111 reg = ctxt->modrm_reg; 1119 1112 else 1120 - reg = (ctxt->b & 7) | ((ctxt->rex_prefix & 1) << 3); 1113 + reg = (ctxt->b & 7) | (ctxt->rex_bits & REX_B ? 8 : 0); 1121 1114 1122 1115 __decode_register_operand(ctxt, op, reg); 1123 1116 } ··· 1136 1129 int rc = X86EMUL_CONTINUE; 1137 1130 ulong modrm_ea = 0; 1138 1131 1139 - ctxt->modrm_reg = ((ctxt->rex_prefix << 1) & 8); /* REX.R */ 1140 - index_reg = (ctxt->rex_prefix << 2) & 8; /* REX.X */ 1141 - base_reg = (ctxt->rex_prefix << 3) & 8; /* REX.B */ 1132 + ctxt->modrm_reg = (ctxt->rex_bits & REX_R ? 8 : 0); 1133 + index_reg = (ctxt->rex_bits & REX_X ? 8 : 0); 1134 + base_reg = (ctxt->rex_bits & REX_B ? 8 : 0); 1142 1135 1143 1136 ctxt->modrm_mod = (ctxt->modrm & 0xc0) >> 6; 1144 1137 ctxt->modrm_reg |= (ctxt->modrm & 0x38) >> 3; ··· 2471 2464 2472 2465 setup_syscalls_segments(&cs, &ss); 2473 2466 2474 - if ((ctxt->rex_prefix & 0x8) != 0x0) 2467 + if (ctxt->rex_bits & REX_W) 2475 2468 usermode = X86EMUL_MODE_PROT64; 2476 2469 else 2477 2470 usermode = X86EMUL_MODE_PROT32; ··· 4857 4850 case 0x40 ... 0x4f: /* REX */ 4858 4851 if (mode != X86EMUL_MODE_PROT64) 4859 4852 goto done_prefixes; 4860 - ctxt->rex_prefix = ctxt->b; 4853 + ctxt->rex_prefix = REX_PREFIX; 4854 + ctxt->rex_bits = ctxt->b & 0xf; 4861 4855 continue; 4862 4856 case 0xf0: /* LOCK */ 4863 4857 ctxt->lock_prefix = 1; ··· 4872 4864 } 4873 4865 4874 4866 /* Any legacy prefix after a REX prefix nullifies its effect. */ 4875 - 4876 - ctxt->rex_prefix = 0; 4867 + ctxt->rex_prefix = REX_NONE; 4868 + ctxt->rex_bits = 0; 4877 4869 } 4878 4870 4879 4871 done_prefixes: 4880 4872 4881 4873 /* REX prefix. */ 4882 - if (ctxt->rex_prefix & 8) 4883 - ctxt->op_bytes = 8; /* REX.W */ 4874 + if (ctxt->rex_bits & REX_W) 4875 + ctxt->op_bytes = 8; 4884 4876 4885 4877 /* Opcode byte(s). */ 4886 4878 if (ctxt->b == 0x0f) { ··· 5146 5138 { 5147 5139 /* Clear fields that are set conditionally but read without a guard. */ 5148 5140 ctxt->rip_relative = false; 5149 - ctxt->rex_prefix = 0; 5141 + ctxt->rex_prefix = REX_NONE; 5142 + ctxt->rex_bits = 0; 5150 5143 ctxt->lock_prefix = 0; 5151 5144 ctxt->op_prefix = false; 5152 5145 ctxt->rep_prefix = 0;
+10 -1
arch/x86/kvm/kvm_emulate.h
··· 319 319 #define NR_EMULATOR_GPRS 8 320 320 #endif 321 321 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 + 322 330 struct x86_emulate_ctxt { 323 331 void *vcpu; 324 332 const struct x86_emulate_ops *ops; ··· 368 360 int (*check_perm)(struct x86_emulate_ctxt *ctxt); 369 361 370 362 bool rip_relative; 371 - u8 rex_prefix; 363 + enum rex_type rex_prefix; 364 + u8 rex_bits; 372 365 u8 lock_prefix; 373 366 u8 rep_prefix; 374 367 /* bitmaps of registers in _regs[] that can be read */