[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v7 6/7] x86emul: support MSR_IMM instructions
Encoding-wise these are very similar to URDMSR/UWRMSR, so existing logic is easy to extend. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> --- RFC only for now, as the VMX part is missing: The existing intercepts can't be re-used unmodified, as those require the MSR index to be fetched from guest ECX. --- v7: New. --- a/tools/tests/x86_emulator/predicates.c +++ b/tools/tests/x86_emulator/predicates.c @@ -1519,6 +1519,8 @@ static const struct vex { { { 0xdf }, 3, T, R, pfx_66, WIG, Ln }, /* vaeskeygenassist */ { { 0xf0 }, 3, T, R, pfx_f2, Wn, L0 }, /* rorx */ }, vex_map7[] = { + { { 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 */ }; --- a/tools/tests/x86_emulator/test_x86_emulator.c +++ b/tools/tests/x86_emulator/test_x86_emulator.c @@ -1569,6 +1569,30 @@ int main(int argc, char **argv) (regs.rip != (unsigned long)&instr[0]) || (uintr_timer != 0x8877665544332211UL) ) goto fail; + printf("okay\n"); + + 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; + regs.rip = (unsigned long)&instr[0]; + regs.rdx = ~gs_base; + rc = x86_emulate(&ctxt, &emulops); + if ( (rc != X86EMUL_OKAY) || + (regs.rip != (unsigned long)&instr[9]) || + (regs.rdx != gs_base) ) + 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; + regs.rip = (unsigned long)&instr[0]; + regs.rsi = 0x665544332211UL; + rc = x86_emulate(&ctxt, &emulops); + if ( (rc != X86EMUL_OKAY) || + (regs.rip != (unsigned long)&instr[9]) || + (gs_base_shadow != 0x665544332211UL) ) + goto fail; emulops.write_msr = NULL; #endif --- a/tools/tests/x86_emulator/x86-emulate.c +++ b/tools/tests/x86_emulator/x86-emulate.c @@ -88,6 +88,7 @@ bool emul_test_init(void) cpu_policy.feat.lkgs = true; cpu_policy.feat.wrmsrns = true; cpu_policy.feat.msrlist = true; + cpu_policy.feat.msr_imm = true; cpu_policy.feat.user_msr = true; cpu_policy.extd.clzero = true; --- a/xen/arch/x86/x86_emulate/decode.c +++ b/xen/arch/x86/x86_emulate/decode.c @@ -1262,8 +1262,9 @@ int x86emul_decode(struct x86_emulate_st case vex_map7: opcode |= MASK_INSR(7, X86EMUL_OPC_EXT_MASK); /* - * No table lookup here for now, as there's only a single - * opcode point (0xf8) populated in map 7. + * No table lookup here for now, as there are only two + * (very similar) opcode points (0xf6, 0xf8) populated + * in map 7. */ d = DstMem | SrcImm | ModRM | Mov; s->op_bytes = 8; --- a/xen/arch/x86/x86_emulate/private.h +++ b/xen/arch/x86/x86_emulate/private.h @@ -600,6 +600,7 @@ amd_like(const struct x86_emulate_ctxt * #define vcpu_has_wrmsrns() (ctxt->cpuid->feat.wrmsrns) #define vcpu_has_avx_ifma() (ctxt->cpuid->feat.avx_ifma) #define vcpu_has_msrlist() (ctxt->cpuid->feat.msrlist) +#define vcpu_has_msr_imm() (ctxt->cpuid->feat.msr_imm) #define vcpu_has_avx_vnni_int8() (ctxt->cpuid->feat.avx_vnni_int8) #define vcpu_has_avx_ne_convert() (ctxt->cpuid->feat.avx_ne_convert) #define vcpu_has_avx_vnni_int16() (ctxt->cpuid->feat.avx_vnni_int16) --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -7037,6 +7037,34 @@ x86_emulate( state->simd_size = simd_none; break; + 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, X86_EXC_UD); + generate_exception_if(vex.l || vex.w, X86_EXC_UD); + generate_exception_if(vex.opcx && ((modrm_reg & 7) || vex.reg != 0xf), + X86_EXC_UD); + vcpu_must_have(msr_imm); + generate_exception_if(!mode_ring0(), X86_EXC_GP, 0); + if ( vex.pfx == vex_f2 ) + { + /* urdmsr */ + fail_if(!ops->read_msr); + if ( (rc = ops->read_msr(imm1, &msr_val, ctxt)) != X86EMUL_OKAY ) + goto done; + dst.val = msr_val; + ASSERT(dst.type == OP_REG); + dst.bytes = 8; + } + else + { + /* wrmsrns */ + fail_if(!ops->write_msr); + if ( (rc = ops->write_msr(imm1, dst.val, ctxt)) != X86EMUL_OKAY ) + goto done; + dst.type = OP_NONE; + } + break; + case X86EMUL_OPC_F3(0x0f38, 0xf8): /* enqcmds r,m512 / uwrmsr r64,r32 */ case X86EMUL_OPC_F2(0x0f38, 0xf8): /* enqcmd r,m512 / urdmsr r32,r64 */ if ( ea.type == OP_MEM ) --- a/xen/include/public/arch-x86/cpufeatureset.h +++ b/xen/include/public/arch-x86/cpufeatureset.h @@ -343,6 +343,7 @@ XEN_CPUFEATURE(BHI_CTRL, 13*32 XEN_CPUFEATURE(MCDT_NO, 13*32+ 5) /*A MCDT_NO */ /* Intel-defined CPU features, CPUID level 0x00000007:1.ecx, word 14 */ +XEN_CPUFEATURE(MSR_IMM, 14*32+ 5) /*s RDMSR/WRMSRNS with immediate operand */ /* Intel-defined CPU features, CPUID level 0x00000007:1.edx, word 15 */ XEN_CPUFEATURE(AVX_VNNI_INT8, 15*32+ 4) /*A AVX-VNNI-INT8 Instructions */ --- a/xen/tools/gen-cpuid.py +++ b/xen/tools/gen-cpuid.py @@ -275,7 +275,7 @@ def crunch_numbers(state): # NO_LMSL indicates the absense of Long Mode Segment Limits, which # have been dropped in hardware. LM: [CX16, PCID, LAHF_LM, PAGE1GB, PKU, NO_LMSL, AMX_TILE, CMPCCXADD, - LKGS, MSRLIST, USER_MSR], + LKGS, MSRLIST, USER_MSR, MSR_IMM], # AMD K6-2+ and K6-III processors shipped with 3DNow+, beyond the # standard 3DNow in the earlier K6 processors.
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |