|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 28/30] x86emul: support APX MSR access insns
Them being direct counterparts of the original VEX-encoded insns, there's
nothing really noteworthy here; code is being re-used as much as possible.
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
--- a/tools/tests/x86_emulator/predicates.c
+++ b/tools/tests/x86_emulator/predicates.c
@@ -2558,6 +2558,13 @@ static const struct evex {
{ { 0xd6 }, 2, T, R, pfx_f2, W0, Ln }, /* vfcmulcph */
{ { 0xd7 }, 2, T, R, pfx_f3, W0, LIG }, /* vfmulcsh */
{ { 0xd7 }, 2, T, R, pfx_f2, W0, LIG }, /* vfcmulcsh */
+}, evex_map7[] = {
+#ifdef __x86_64__
+ { { 0xf6, 0xc0 }, 6, F, N, pfx_f3, W0, L0 }, /* wrmsrns */
+ { { 0xf6, 0xc0 }, 6, F, N, pfx_f2, W0, L0 }, /* rdmsr */
+ { { 0xf8, 0xc0 }, 6, F, N, pfx_f3, W0, L0 }, /* uwrmsr */
+ { { 0xf8, 0xc0 }, 6, F, N, pfx_f2, W0, L0 }, /* urdmsr */
+#endif
};
#undef CND
@@ -2572,6 +2579,7 @@ static const struct {
{ evex_map4, ARRAY_SIZE(evex_map4) },
{ evex_map5, ARRAY_SIZE(evex_map5) },
{ evex_map6, ARRAY_SIZE(evex_map6) },
+ { evex_map7, ARRAY_SIZE(evex_map7) },
};
#undef Wn
--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -1960,6 +1960,22 @@ int main(int argc, char **argv)
goto fail;
printf("okay\n");
+ if ( cpu_has_apx_f )
+ {
+ printf("%-40s", "Testing urdmsr %r26,%r25...");
+ instr[0] = 0x62; instr[1] = 0x4c; instr[2] = 0x7f; instr[3] = 0x08;
+ instr[4] = 0xf8; instr[5] = 0xd1;
+ regs.rip = (unsigned long)&instr[0];
+ load_egpr(26, MSR_IA32_APERF);
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( (rc != X86EMUL_OKAY) ||
+ (regs.rip != (unsigned long)&instr[6]) ||
+ !check_egpr(25,
+ (((uint64_t)APERF_HI_VALUE << 32) | APERF_LO_VALUE)) )
+ goto fail;
+ printf("okay\n");
+ }
+
printf("%-40s", "Testing urdmsr $MSR_IA32_APERF,%rdx...");
instr[0] = 0xc4; instr[1] = 0xe7; instr[2] = 0x7b; instr[3] = 0xf8;
instr[4] = 0xc2;
*(uint32_t *)&instr[5] = MSR_IA32_APERF;
@@ -1975,6 +1991,22 @@ int main(int argc, char **argv)
i = cpu_policy.feat.utmr;
cpu_policy.feat.utmr = true;
+ if ( cpu_has_apx_f )
+ {
+ printf("%-40s", "Testing urdmsr $MSR_IA32_APERF,%r18...");
+ instr[0] = 0x62; instr[1] = 0xff; instr[2] = 0x7f; instr[3] = 0x08;
+ instr[4] = 0xf8; instr[5] = 0xc2;
+ *(uint32_t *)&instr[6] = MSR_IA32_APERF;
+ regs.rip = (unsigned long)&instr[0];
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( (rc != X86EMUL_OKAY) ||
+ (regs.rip != (unsigned long)&instr[10]) ||
+ !check_egpr(18,
+ (((uint64_t)APERF_HI_VALUE << 32) | APERF_LO_VALUE)) )
+ goto fail;
+ printf("okay\n");
+ }
+
printf("%-40s", "Testing uwrmsr %rdi,%rsi...");
instr[0] = 0xf3; instr[1] = 0x0f; instr[2] = 0x38; instr[3] = 0xf8;
instr[4] = 0xf7;
regs.rip = (unsigned long)&instr[0];
@@ -1987,6 +2019,22 @@ int main(int argc, char **argv)
goto fail;
printf("okay\n");
+ if ( cpu_has_apx_f )
+ {
+ printf("%-40s", "Testing uwrmsr %r31,%r30...");
+ instr[0] = 0x62; instr[1] = 0x4c; instr[2] = 0x7e; instr[3] = 0x08;
+ instr[4] = 0xf8; instr[5] = 0xf7;
+ regs.rip = (unsigned long)&instr[0];
+ load_egpr(30, MSR_UINTR_TIMER);
+ load_egpr(31, 0x1122334455667788UL);
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( (rc != X86EMUL_OKAY) ||
+ (regs.rip != (unsigned long)&instr[6]) ||
+ (uintr_timer != 0x1122334455667788UL) )
+ goto fail;
+ printf("okay\n");
+ }
+
printf("%-40s", "Testing uwrmsr %rsi,$MSR_UINTR_TIMER...");
instr[0] = 0xc4; instr[1] = 0xe7; instr[2] = 0x7a; instr[3] = 0xf8;
instr[4] = 0xc6;
*(uint32_t *)&instr[5] = MSR_UINTR_TIMER;
@@ -1999,8 +2047,6 @@ int main(int argc, char **argv)
goto fail;
printf("okay\n");
- cpu_policy.feat.utmr = i;
-
printf("%-40s", "Testing uwrmsr %rsi,$MSR_UARCH_MISC_CTRL...");
*(uint32_t *)&instr[5] = MSR_UARCH_MISC_CTRL;
regs.rip = (unsigned long)&instr[0];
@@ -2011,6 +2057,24 @@ int main(int argc, char **argv)
goto fail;
printf("okay\n");
+ if ( cpu_has_apx_f )
+ {
+ printf("%-40s", "Testing uwrmsr %r30,$MSR_UINTR_TIMER...");
+ instr[0] = 0x62; instr[1] = 0xdf; instr[2] = 0x7e; instr[3] = 0x08;
+ instr[4] = 0xf8; instr[5] = 0xc6;
+ *(uint32_t *)&instr[6] = MSR_UINTR_TIMER;
+ regs.rip = (unsigned long)&instr[0];
+ load_egpr(30, 0x9988776655443322UL);
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( (rc != X86EMUL_OKAY) ||
+ (regs.rip != (unsigned long)&instr[10]) ||
+ (uintr_timer != 0x9988776655443322UL) )
+ goto fail;
+ printf("okay\n");
+ }
+
+ cpu_policy.feat.utmr = i;
+
printf("%-40s", "Testing rdmsr $MSR_GS_BASE,%rdx...");
instr[0] = 0xc4; instr[1] = 0xe7; instr[2] = 0x7b; instr[3] = 0xf6;
instr[4] = 0xc2;
*(uint32_t *)&instr[5] = MSR_GS_BASE;
@@ -2023,6 +2087,35 @@ int main(int argc, char **argv)
goto fail;
printf("okay\n");
+ if ( cpu_has_apx_f )
+ {
+ printf("%-40s", "Testing rdmsr $MSR_GS_BASE,%r26...");
+ instr[0] = 0x62; instr[1] = 0xdf; instr[2] = 0x7f; instr[3] = 0x08;
+ instr[4] = 0xf6; instr[5] = 0xc2;
+ *(uint32_t *)&instr[6] = MSR_GS_BASE;
+ regs.rip = (unsigned long)&instr[0];
+ load_egpr(26, ~gs_base);
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( (rc != X86EMUL_OKAY) ||
+ (regs.rip != (unsigned long)&instr[10]) ||
+ !check_egpr(26, gs_base) )
+ goto fail;
+ printf("okay\n");
+
+ printf("%-40s", "Testing wrmsrns %r22,$MSR_SHADOW_GS_BASE...");
+ instr[0] = 0x62; instr[1] = 0xff; instr[2] = 0x7e; instr[3] = 0x08;
+ instr[4] = 0xf6; instr[5] = 0xc6;
+ *(uint32_t *)&instr[6] = MSR_SHADOW_GS_BASE;
+ regs.rip = (unsigned long)&instr[0];
+ load_egpr(22, 0x776655443322UL);
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( (rc != X86EMUL_OKAY) ||
+ (regs.rip != (unsigned long)&instr[10]) ||
+ (gs_base_shadow != 0x776655443322UL) )
+ goto fail;
+ printf("okay\n");
+ }
+
printf("%-40s", "Testing wrmsrns %rsi,$MSR_SHADOW_GS_BASE...");
instr[0] = 0xc4; instr[1] = 0xe7; instr[2] = 0x7a; instr[3] = 0xf6;
instr[4] = 0xc6;
*(uint32_t *)&instr[5] = MSR_SHADOW_GS_BASE;
--- a/xen/arch/x86/x86_emulate/decode.c
+++ b/xen/arch/x86/x86_emulate/decode.c
@@ -1469,8 +1469,15 @@ decode_map4(struct x86_emulate_state *s,
}
break;
- case 0xf8: /* movdir64b / enqcmd{,s} */
+ case 0xf8: /* movdir64b / enqcmd{,s} / u{rd,wr}msr */
/* Make these match their legacy forms. */
+ if ( s->modrm_mod == 3 )
+ {
+ s->desc = DstMem | SrcReg | Mov;
+ s->op_bytes = 8;
+ s->simd_size = simd_none;
+ break;
+ }
s->desc = DstReg | Mov;
s->op_bytes = 0;
break;
@@ -1892,6 +1899,8 @@ int x86emul_decode(struct x86_emulate_st
break;
case vex_map7:
+ if ( evex_encoded() )
+ s->promoted_evex = true;
opcode |= MASK_INSR(7, X86EMUL_OPC_EXT_MASK);
/*
* No table lookup here for now, as there are only two
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -7589,6 +7589,11 @@ x86_emulate(
state->simd_size = simd_none;
break;
+ case X86EMUL_OPC_EVEX_F3(7, 0xf6): /* wrmsrns r64,imm32 */
+ case X86EMUL_OPC_EVEX_F2(7, 0xf6): /* rdmsr imm32,r64 */
+ generate_exception_if((evex.lr || evex.brs || evex.opmsk || !evex.RX),
+ X86_EXC_UD);
+ fallthrough;
case X86EMUL_OPC_VEX_F3(7, 0xf6): /* wrmsrns r64,imm32 */
case X86EMUL_OPC_VEX_F2(7, 0xf6): /* rdmsr imm32,r64 */
generate_exception_if((!mode_64bit() || ea.type != OP_REG ||
@@ -7620,16 +7625,26 @@ x86_emulate(
case X86EMUL_OPC_F3(0x0f38, 0xf8): /* enqcmds r,m512 / uwrmsr r64,r32 */
case X86EMUL_OPC_F2(0x0f38, 0xf8): /* enqcmd r,m512 / urdmsr r32,r64 */
+ case X86EMUL_OPC_EVEX_F3(4, 0xf8): /* enqcmds r,m512 / uwrmsr r64,r32 */
+ case X86EMUL_OPC_EVEX_F2(4, 0xf8): /* enqcmd r,m512 / urdmsr r32,r64 */
if ( ea.type == OP_MEM )
goto enqcmd;
imm1 = src.val;
fallthrough;
+ case X86EMUL_OPC_EVEX_F3(7, 0xf8): /* uwrmsr r64,imm32 */
+ case X86EMUL_OPC_EVEX_F2(7, 0xf8): /* urdmsr imm32,r64 */
+ if ( evex.opcx == vex_map7 )
+ generate_exception_if((evex.lr || evex.brs || evex.opmsk ||
+ !evex.RX),
+ X86_EXC_UD);
+ fallthrough;
case X86EMUL_OPC_VEX_F3(7, 0xf8): /* uwrmsr r64,imm32 */
case X86EMUL_OPC_VEX_F2(7, 0xf8): /* urdmsr imm32,r64 */
generate_exception_if(!mode_64bit() || ea.type != OP_REG, X86_EXC_UD);
generate_exception_if(vex.l || vex.w, X86_EXC_UD);
- generate_exception_if(vex.opcx && ((modrm_reg & 7) || vex.reg != 0xf),
+ generate_exception_if(vex.opcx == vex_map7 && (modrm_reg & 7),
X86_EXC_UD);
+ generate_exception_if(vex.opcx && vex.reg != 0xf, X86_EXC_UD);
vcpu_must_have(user_msr);
fail_if(!ops->read_msr);
if ( ops->read_msr(MSR_USER_MSR_CTL, &msr_val, ctxt) != X86EMUL_OKAY )
@@ -7684,9 +7699,6 @@ x86_emulate(
}
break;
- case X86EMUL_OPC_EVEX_F3(4, 0xf8): /* enqcmds r,m512 */
- case X86EMUL_OPC_EVEX_F2(4, 0xf8): /* enqcmd r,m512 */
- generate_exception_if(ea.type != OP_MEM, X86_EXC_UD);
enqcmd:
vcpu_must_have(enqcmd);
generate_exception_if(vex.pfx != vex_f2 && !mode_ring0(), X86_EXC_GP,
0);
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |