From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH 5/8] x86emul: support TBM insns Date: Fri, 13 Jan 2017 08:32:49 -0700 Message-ID: <58790131020000780012FF5B@prv-mh.provo.novell.com> References: <5878FC41020000780012FF02@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part8AB3A731.1__=" Return-path: Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cS3qW-0008Ae-Jo for xen-devel@lists.xenproject.org; Fri, 13 Jan 2017 15:32:52 +0000 In-Reply-To: <5878FC41020000780012FF02@prv-mh.provo.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel Cc: Andrew Cooper List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__Part8AB3A731.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Signed-off-by: Jan Beulich --- a/tools/tests/x86_emulator/test_x86_emulator.c +++ b/tools/tests/x86_emulator/test_x86_emulator.c @@ -1244,6 +1244,234 @@ int main(int argc, char **argv) printf("okay\n"); } =20 + printf("%-40s", "Testing bextr $0x0a03,(%ecx),%ebx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(bextr_imm); +#ifdef __x86_64__ + decl_insn(bextr64_imm); +#endif + + asm volatile ( put_insn(bextr_imm, "bextr $0x0a03, (%0), %%ebx") + :: "c" (NULL) ); + set_insn(bextr_imm); + + *res =3D 0xfedcba98; + regs.ecx =3D (unsigned long)res; + regs.eflags =3D 0xa43; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || regs.ebx !=3D ((*res >> 3) & = 0x3ff) || + *res !=3D 0xfedcba98 || + (regs.eflags & 0xf6b) !=3D 0x202 || !check_eip(bextr_imm) ) + goto fail; + printf("okay\n"); +#ifdef __x86_64__ + printf("%-40s", "Testing bextr $0x211e,(%r10),%r11..."); + + asm volatile ( put_insn(bextr64_imm, "bextr $0x211e, (%r10), = %r11") ); + set_insn(bextr64_imm); + + res[0] =3D 0x76543210; + res[1] =3D 0xfedcba98; + regs.r10 =3D (unsigned long)res; + regs.eflags =3D 0xa43; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || + regs.r11 !=3D (((unsigned long)(res[1] << 1) << 1) | + (res[0] >> 30)) || + res[0] !=3D 0x76543210 || res[1] !=3D 0xfedcba98 || + (regs.eflags & 0xf6b) !=3D 0x202 || !check_eip(bextr64_imm) = ) + goto fail; + printf("okay\n"); +#endif + } + else + printf("skipped\n"); + + res[0] =3D 0xfedcba98; + res[1] =3D 0x01234567; + regs.edx =3D (unsigned long)res; + + printf("%-40s", "Testing blcfill 4(%edx),%ecx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(blcfill); + + asm volatile ( put_insn(blcfill, "blcfill 4(%0), %%ecx") + :: "d" (NULL) ); + set_insn(blcfill); + + regs.eflags =3D 0xac3; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 || + regs.ecx !=3D ((res[1] + 1) & res[1]) || + (regs.eflags & 0xfeb) !=3D 0x202 || !check_eip(blcfill) ) + goto fail; + printf("okay\n"); + } + else + printf("skipped\n"); + + printf("%-40s", "Testing blci 4(%edx),%ecx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(blci); + + asm volatile ( put_insn(blci, "blci 4(%0), %%ecx") + :: "d" (NULL) ); + set_insn(blci); + + regs.eflags =3D 0xac3; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 || + regs.ecx !=3D (~(res[1] + 1) | res[1]) || + (regs.eflags & 0xfeb) !=3D 0x282 || !check_eip(blci) ) + goto fail; + printf("okay\n"); + } + else + printf("skipped\n"); + + printf("%-40s", "Testing blcic 4(%edx),%ecx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(blcic); + + asm volatile ( put_insn(blcic, "blcic 4(%0), %%ecx") + :: "d" (NULL) ); + set_insn(blcic); + + regs.eflags =3D 0xac3; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 || + regs.ecx !=3D ((res[1] + 1) & ~res[1]) || + (regs.eflags & 0xfeb) !=3D 0x202 || !check_eip(blcic) ) + goto fail; + printf("okay\n"); + } + else + printf("skipped\n"); + + printf("%-40s", "Testing blcmsk 4(%edx),%ecx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(blcmsk); + + asm volatile ( put_insn(blcmsk, "blcmsk 4(%0), %%ecx") + :: "d" (NULL) ); + set_insn(blcmsk); + + regs.eflags =3D 0xac3; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 || + regs.ecx !=3D ((res[1] + 1) ^ res[1]) || + (regs.eflags & 0xfeb) !=3D 0x202 || !check_eip(blcmsk) ) + goto fail; + printf("okay\n"); + } + else + printf("skipped\n"); + + printf("%-40s", "Testing blcs 4(%edx),%ecx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(blcs); + + asm volatile ( put_insn(blcs, "blcs 4(%0), %%ecx") + :: "d" (NULL) ); + set_insn(blcs); + + regs.eflags =3D 0xac3; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 || + regs.ecx !=3D ((res[1] + 1) | res[1]) || + (regs.eflags & 0xfeb) !=3D 0x202 || !check_eip(blcs) ) + goto fail; + printf("okay\n"); + } + else + printf("skipped\n"); + + printf("%-40s", "Testing blsfill (%edx),%ecx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(blsfill); + + asm volatile ( put_insn(blsfill, "blsfill (%0), %%ecx") + :: "d" (NULL) ); + set_insn(blsfill); + + regs.eflags =3D 0xac3; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || res[0] !=3D 0xfedcba98 || + regs.ecx !=3D ((res[0] - 1) | res[0]) || + (regs.eflags & 0xfeb) !=3D 0x282 || !check_eip(blsfill) ) + goto fail; + printf("okay\n"); + } + else + printf("skipped\n"); + + printf("%-40s", "Testing blsic (%edx),%ecx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(blsic); + + asm volatile ( put_insn(blsic, "blsic (%0), %%ecx") + :: "d" (NULL) ); + set_insn(blsic); + + regs.eflags =3D 0xac3; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || res[0] !=3D 0xfedcba98 || + regs.ecx !=3D ((res[0] - 1) | ~res[0]) || + (regs.eflags & 0xfeb) !=3D 0x282 || !check_eip(blsic) ) + goto fail; + printf("okay\n"); + } + else + printf("skipped\n"); + + printf("%-40s", "Testing t1mskc 4(%edx),%ecx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(t1mskc); + + asm volatile ( put_insn(t1mskc, "t1mskc 4(%0), %%ecx") + :: "d" (NULL) ); + set_insn(t1mskc); + + regs.eflags =3D 0xac3; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 || + regs.ecx !=3D ((res[1] + 1) | ~res[1]) || + (regs.eflags & 0xfeb) !=3D 0x282 || !check_eip(t1mskc) ) + goto fail; + printf("okay\n"); + } + else + printf("skipped\n"); + + printf("%-40s", "Testing tzmsk (%edx),%ecx..."); + if ( stack_exec && cpu_has_tbm ) + { + decl_insn(tzmsk); + + asm volatile ( put_insn(tzmsk, "tzmsk (%0), %%ecx") + :: "d" (NULL) ); + set_insn(tzmsk); + + regs.eflags =3D 0xac3; + rc =3D x86_emulate(&ctxt, &emulops); + if ( (rc !=3D X86EMUL_OKAY) || res[0] !=3D 0xfedcba98 || + regs.ecx !=3D ((res[0] - 1) & ~res[0]) || + (regs.eflags & 0xfeb) !=3D 0x202 || !check_eip(tzmsk) ) + goto fail; + printf("okay\n"); + } + else + printf("skipped\n"); + printf("%-40s", "Testing movq %mm3,(%ecx)..."); if ( stack_exec && cpu_has_mmx ) { --- a/tools/tests/x86_emulator/x86_emulate.h +++ b/tools/tests/x86_emulator/x86_emulate.h @@ -125,6 +125,12 @@ static inline uint64_t xgetbv(uint32_t x (res.b & (1U << 8)) !=3D 0; \ }) =20 +#define cpu_has_tbm ({ \ + struct cpuid_leaf res; \ + emul_test_cpuid(0x80000001, 0, &res, NULL); \ + (res.c & (1U << 21)) !=3D 0; \ +}) + int emul_test_cpuid( uint32_t leaf, uint32_t subleaf, --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -1355,6 +1355,7 @@ static bool vcpu_has( #define vcpu_has_cr8_legacy() vcpu_has(0x80000001, ECX, 4, ctxt, ops) #define vcpu_has_lzcnt() vcpu_has(0x80000001, ECX, 5, ctxt, ops) #define vcpu_has_misalignsse() vcpu_has(0x80000001, ECX, 7, ctxt, ops) +#define vcpu_has_tbm() vcpu_has(0x80000001, ECX, 21, ctxt, ops) #define vcpu_has_bmi1() vcpu_has( 7, EBX, 3, ctxt, ops) #define vcpu_has_hle() vcpu_has( 7, EBX, 4, ctxt, ops) #define vcpu_has_bmi2() vcpu_has( 7, EBX, 8, ctxt, ops) @@ -6014,6 +6015,85 @@ x86_emulate( asm ( "rorl %b1,%k0" : "=3Dg" (dst.val) : "c" (imm1), "0" = (src.val) ); break; =20 + case X86EMUL_OPC(0x8f09, 0x01): /* XOP Grp1 */ + switch ( modrm_reg & 7 ) + { + case 1: /* blcfill r/m,r */ + case 2: /* blsfill r/m,r */ + case 3: /* blcs r/m,r */ + case 4: /* tzmsk r/m,r */ + case 5: /* blcic r/m,r */ + case 6: /* blsic r/m,r */ + case 7: /* t1mskc r/m,r */ + host_and_vcpu_must_have(tbm); + break; + default: + goto cannot_emulate; + } + + xop_09_rm_rv: + { + uint8_t *buf =3D get_stub(stub); + typeof(vex) *pxop =3D container_of(buf + 1, typeof(vex), raw[0]); + + generate_exception_if(vex.l, EXC_UD); + + buf[0] =3D 0x8f; + *pxop =3D vex; + pxop->b =3D 1; + pxop->r =3D 1; + pxop->reg =3D ~0; /* rAX */ + buf[3] =3D b; + buf[4] =3D (modrm & 0x38) | 0x01; /* r/m=3D(%rCX) */ + buf[5] =3D 0xc3; + + dst.reg =3D decode_register(~vex.reg & (mode_64bit() ? 0xf : 7), + &_regs, 0); + emulate_stub([dst] "=3D&a" (dst.val), "c" (&src.val)); + + put_stub(stub); + break; + } + + case X86EMUL_OPC(0x8f09, 0x02): /* XOP Grp2 */ + switch ( modrm_reg & 7 ) + { + case 1: /* blcmsk r/m,r */ + case 6: /* blci r/m,r */ + host_and_vcpu_must_have(tbm); + goto xop_09_rm_rv; + } + goto cannot_emulate; + + case X86EMUL_OPC(0x8f0a, 0x10): /* bextr imm,r/m,r */ + { + uint8_t *buf =3D get_stub(stub); + typeof(vex) *pxop =3D container_of(buf + 1, typeof(vex), raw[0]); + + host_and_vcpu_must_have(tbm); + generate_exception_if(vex.l || vex.reg !=3D 0xf, EXC_UD); + + if ( ea.type =3D=3D OP_REG ) + src.val =3D *ea.reg; + else if ( (rc =3D read_ulong(ea.mem.seg, ea.mem.off, &src.val, = op_bytes, + ctxt, ops)) !=3D X86EMUL_OKAY ) + goto done; + + buf[0] =3D 0x8f; + *pxop =3D vex; + pxop->b =3D 1; + pxop->r =3D 1; + buf[3] =3D b; + buf[4] =3D 0x09; /* reg=3DrCX r/m=3D(%rCX) */ + *(uint32_t *)(buf + 5) =3D imm1; + buf[9] =3D 0xc3; + + emulate_stub([dst] "=3D&c" (dst.val), "[dst]" (&src.val)); + + put_stub(stub); + break; + } + default: goto cannot_emulate; } --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -74,6 +74,7 @@ #define cpu_has_eist boot_cpu_has(X86_FEATURE_EIST) #define cpu_has_hypervisor boot_cpu_has(X86_FEATURE_HYPERVISOR) #define cpu_has_cmp_legacy boot_cpu_has(X86_FEATURE_CMP_LEGACY) +#define cpu_has_tbm boot_cpu_has(X86_FEATURE_TBM) =20 enum _cache_type { CACHE_TYPE_NULL =3D 0, --=__Part8AB3A731.1__= Content-Type: text/plain; name="x86emul-TBM.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86emul-TBM.patch" x86emul: support TBM insns=0A=0ASigned-off-by: Jan Beulich =0A=0A--- a/tools/tests/x86_emulator/test_x86_emulator.c=0A+++ = b/tools/tests/x86_emulator/test_x86_emulator.c=0A@@ -1244,6 +1244,234 @@ = int main(int argc, char **argv)=0A printf("okay\n");=0A }=0A = =0A+ printf("%-40s", "Testing bextr $0x0a03,(%ecx),%ebx...");=0A+ if = ( stack_exec && cpu_has_tbm )=0A+ {=0A+ decl_insn(bextr_imm);=0A+= #ifdef __x86_64__=0A+ decl_insn(bextr64_imm);=0A+#endif=0A+=0A+ = asm volatile ( put_insn(bextr_imm, "bextr $0x0a03, (%0), %%ebx")=0A+ = :: "c" (NULL) );=0A+ set_insn(bextr_imm);=0A+=0A+= *res =3D 0xfedcba98;=0A+ regs.ecx =3D (unsigned = long)res;=0A+ regs.eflags =3D 0xa43;=0A+ rc =3D x86_emulate(&= ctxt, &emulops);=0A+ if ( (rc !=3D X86EMUL_OKAY) || regs.ebx !=3D = ((*res >> 3) & 0x3ff) ||=0A+ *res !=3D 0xfedcba98 ||=0A+ = (regs.eflags & 0xf6b) !=3D 0x202 || !check_eip(bextr_imm) )=0A+ = goto fail;=0A+ printf("okay\n");=0A+#ifdef __x86_64__=0A+ = printf("%-40s", "Testing bextr $0x211e,(%r10),%r11...");=0A+=0A+ = asm volatile ( put_insn(bextr64_imm, "bextr $0x211e, (%r10), %r11") );=0A+ = set_insn(bextr64_imm);=0A+=0A+ res[0] =3D 0x76543210;=0A= + res[1] =3D 0xfedcba98;=0A+ regs.r10 =3D (unsigned = long)res;=0A+ regs.eflags =3D 0xa43;=0A+ rc =3D x86_emulate(&= ctxt, &emulops);=0A+ if ( (rc !=3D X86EMUL_OKAY) ||=0A+ = regs.r11 !=3D (((unsigned long)(res[1] << 1) << 1) |=0A+ = (res[0] >> 30)) ||=0A+ res[0] !=3D 0x76543210 || res[1] = !=3D 0xfedcba98 ||=0A+ (regs.eflags & 0xf6b) !=3D 0x202 || = !check_eip(bextr64_imm) )=0A+ goto fail;=0A+ printf("okay= \n");=0A+#endif=0A+ }=0A+ else=0A+ printf("skipped\n");=0A+=0A= + res[0] =3D 0xfedcba98;=0A+ res[1] =3D 0x01234567;=0A+ = regs.edx =3D (unsigned long)res;=0A+=0A+ printf("%-40s", "Testing = blcfill 4(%edx),%ecx...");=0A+ if ( stack_exec && cpu_has_tbm )=0A+ = {=0A+ decl_insn(blcfill);=0A+=0A+ asm volatile ( put_insn(blc= fill, "blcfill 4(%0), %%ecx")=0A+ :: "d" (NULL) = );=0A+ set_insn(blcfill);=0A+=0A+ regs.eflags =3D 0xac3;=0A+ = rc =3D x86_emulate(&ctxt, &emulops);=0A+ if ( (rc !=3D = X86EMUL_OKAY) || res[1] !=3D 0x01234567 ||=0A+ regs.ecx !=3D = ((res[1] + 1) & res[1]) ||=0A+ (regs.eflags & 0xfeb) !=3D = 0x202 || !check_eip(blcfill) )=0A+ goto fail;=0A+ = printf("okay\n");=0A+ }=0A+ else=0A+ printf("skipped\n");=0A+= =0A+ printf("%-40s", "Testing blci 4(%edx),%ecx...");=0A+ if ( = stack_exec && cpu_has_tbm )=0A+ {=0A+ decl_insn(blci);=0A+=0A+ = asm volatile ( put_insn(blci, "blci 4(%0), %%ecx")=0A+ = :: "d" (NULL) );=0A+ set_insn(blci);=0A+=0A+ = regs.eflags =3D 0xac3;=0A+ rc =3D x86_emulate(&ctxt, &emulops);=0A+ = if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 ||=0A+ = regs.ecx !=3D (~(res[1] + 1) | res[1]) ||=0A+ (regs.eflags= & 0xfeb) !=3D 0x282 || !check_eip(blci) )=0A+ goto fail;=0A+ = printf("okay\n");=0A+ }=0A+ else=0A+ printf("skipped\n");= =0A+=0A+ printf("%-40s", "Testing blcic 4(%edx),%ecx...");=0A+ if ( = stack_exec && cpu_has_tbm )=0A+ {=0A+ decl_insn(blcic);=0A+=0A+ = asm volatile ( put_insn(blcic, "blcic 4(%0), %%ecx")=0A+ = :: "d" (NULL) );=0A+ set_insn(blcic);=0A+=0A+ = regs.eflags =3D 0xac3;=0A+ rc =3D x86_emulate(&ctxt, &emulops);=0A+ = if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 ||=0A+ = regs.ecx !=3D ((res[1] + 1) & ~res[1]) ||=0A+ (regs.eflags= & 0xfeb) !=3D 0x202 || !check_eip(blcic) )=0A+ goto fail;=0A+ = printf("okay\n");=0A+ }=0A+ else=0A+ printf("skipped\n")= ;=0A+=0A+ printf("%-40s", "Testing blcmsk 4(%edx),%ecx...");=0A+ if = ( stack_exec && cpu_has_tbm )=0A+ {=0A+ decl_insn(blcmsk);=0A+=0A= + asm volatile ( put_insn(blcmsk, "blcmsk 4(%0), %%ecx")=0A+ = :: "d" (NULL) );=0A+ set_insn(blcmsk);=0A+=0A+ = regs.eflags =3D 0xac3;=0A+ rc =3D x86_emulate(&ctxt, &emulops);=0A+= if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 ||=0A+ = regs.ecx !=3D ((res[1] + 1) ^ res[1]) ||=0A+ (regs.eflags= & 0xfeb) !=3D 0x202 || !check_eip(blcmsk) )=0A+ goto fail;=0A+ = printf("okay\n");=0A+ }=0A+ else=0A+ printf("skipped\n"= );=0A+=0A+ printf("%-40s", "Testing blcs 4(%edx),%ecx...");=0A+ if ( = stack_exec && cpu_has_tbm )=0A+ {=0A+ decl_insn(blcs);=0A+=0A+ = asm volatile ( put_insn(blcs, "blcs 4(%0), %%ecx")=0A+ = :: "d" (NULL) );=0A+ set_insn(blcs);=0A+=0A+ = regs.eflags =3D 0xac3;=0A+ rc =3D x86_emulate(&ctxt, &emulops);=0A+ = if ( (rc !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 ||=0A+ = regs.ecx !=3D ((res[1] + 1) | res[1]) ||=0A+ (regs.eflags = & 0xfeb) !=3D 0x202 || !check_eip(blcs) )=0A+ goto fail;=0A+ = printf("okay\n");=0A+ }=0A+ else=0A+ printf("skipped\n");= =0A+=0A+ printf("%-40s", "Testing blsfill (%edx),%ecx...");=0A+ if ( = stack_exec && cpu_has_tbm )=0A+ {=0A+ decl_insn(blsfill);=0A+=0A+= asm volatile ( put_insn(blsfill, "blsfill (%0), %%ecx")=0A+ = :: "d" (NULL) );=0A+ set_insn(blsfill);=0A+=0A+ = regs.eflags =3D 0xac3;=0A+ rc =3D x86_emulate(&ctxt, &emulops);=0A= + if ( (rc !=3D X86EMUL_OKAY) || res[0] !=3D 0xfedcba98 ||=0A+ = regs.ecx !=3D ((res[0] - 1) | res[0]) ||=0A+ (regs.eflag= s & 0xfeb) !=3D 0x282 || !check_eip(blsfill) )=0A+ goto = fail;=0A+ printf("okay\n");=0A+ }=0A+ else=0A+ = printf("skipped\n");=0A+=0A+ printf("%-40s", "Testing blsic (%edx),%ecx.= ..");=0A+ if ( stack_exec && cpu_has_tbm )=0A+ {=0A+ = decl_insn(blsic);=0A+=0A+ asm volatile ( put_insn(blsic, "blsic = (%0), %%ecx")=0A+ :: "d" (NULL) );=0A+ = set_insn(blsic);=0A+=0A+ regs.eflags =3D 0xac3;=0A+ rc =3D = x86_emulate(&ctxt, &emulops);=0A+ if ( (rc !=3D X86EMUL_OKAY) || = res[0] !=3D 0xfedcba98 ||=0A+ regs.ecx !=3D ((res[0] - 1) | = ~res[0]) ||=0A+ (regs.eflags & 0xfeb) !=3D 0x282 || !check_eip(= blsic) )=0A+ goto fail;=0A+ printf("okay\n");=0A+ = }=0A+ else=0A+ printf("skipped\n");=0A+=0A+ printf("%-40s", = "Testing t1mskc 4(%edx),%ecx...");=0A+ if ( stack_exec && cpu_has_tbm = )=0A+ {=0A+ decl_insn(t1mskc);=0A+=0A+ asm volatile ( = put_insn(t1mskc, "t1mskc 4(%0), %%ecx")=0A+ :: "d" = (NULL) );=0A+ set_insn(t1mskc);=0A+=0A+ regs.eflags =3D = 0xac3;=0A+ rc =3D x86_emulate(&ctxt, &emulops);=0A+ if ( (rc = !=3D X86EMUL_OKAY) || res[1] !=3D 0x01234567 ||=0A+ regs.ecx = !=3D ((res[1] + 1) | ~res[1]) ||=0A+ (regs.eflags & 0xfeb) = !=3D 0x282 || !check_eip(t1mskc) )=0A+ goto fail;=0A+ = printf("okay\n");=0A+ }=0A+ else=0A+ printf("skipped\n");=0A+= =0A+ printf("%-40s", "Testing tzmsk (%edx),%ecx...");=0A+ if ( = stack_exec && cpu_has_tbm )=0A+ {=0A+ decl_insn(tzmsk);=0A+=0A+ = asm volatile ( put_insn(tzmsk, "tzmsk (%0), %%ecx")=0A+ = :: "d" (NULL) );=0A+ set_insn(tzmsk);=0A+=0A+ = regs.eflags =3D 0xac3;=0A+ rc =3D x86_emulate(&ctxt, &emulops);=0A+ = if ( (rc !=3D X86EMUL_OKAY) || res[0] !=3D 0xfedcba98 ||=0A+ = regs.ecx !=3D ((res[0] - 1) & ~res[0]) ||=0A+ (regs.eflags= & 0xfeb) !=3D 0x202 || !check_eip(tzmsk) )=0A+ goto fail;=0A+ = printf("okay\n");=0A+ }=0A+ else=0A+ printf("skipped\n")= ;=0A+=0A printf("%-40s", "Testing movq %mm3,(%ecx)...");=0A if ( = stack_exec && cpu_has_mmx )=0A {=0A--- a/tools/tests/x86_emulator/x86_e= mulate.h=0A+++ b/tools/tests/x86_emulator/x86_emulate.h=0A@@ -125,6 = +125,12 @@ static inline uint64_t xgetbv(uint32_t x=0A (res.b & (1U << = 8)) !=3D 0; \=0A })=0A =0A+#define cpu_has_tbm ({ \=0A+ struct = cpuid_leaf res; \=0A+ emul_test_cpuid(0x80000001, 0, &res, NULL); \=0A+ = (res.c & (1U << 21)) !=3D 0; \=0A+})=0A+=0A int emul_test_cpuid(=0A = uint32_t leaf,=0A uint32_t subleaf,=0A--- a/xen/arch/x86/x86_emulate/x8= 6_emulate.c=0A+++ b/xen/arch/x86/x86_emulate/x86_emulate.c=0A@@ -1355,6 = +1355,7 @@ static bool vcpu_has(=0A #define vcpu_has_cr8_legacy() = vcpu_has(0x80000001, ECX, 4, ctxt, ops)=0A #define vcpu_has_lzcnt() = vcpu_has(0x80000001, ECX, 5, ctxt, ops)=0A #define vcpu_has_misalignsse() = vcpu_has(0x80000001, ECX, 7, ctxt, ops)=0A+#define vcpu_has_tbm() = vcpu_has(0x80000001, ECX, 21, ctxt, ops)=0A #define vcpu_has_bmi1() = vcpu_has( 7, EBX, 3, ctxt, ops)=0A #define vcpu_has_hle() = vcpu_has( 7, EBX, 4, ctxt, ops)=0A #define vcpu_has_bmi2() = vcpu_has( 7, EBX, 8, ctxt, ops)=0A@@ -6014,6 +6015,85 @@ = x86_emulate(=0A asm ( "rorl %b1,%k0" : "=3Dg" (dst.val) : "c" = (imm1), "0" (src.val) );=0A break;=0A =0A+ case X86EMUL_OPC(0x8f= 09, 0x01): /* XOP Grp1 */=0A+ switch ( modrm_reg & 7 )=0A+ = {=0A+ case 1: /* blcfill r/m,r */=0A+ case 2: /* blsfill = r/m,r */=0A+ case 3: /* blcs r/m,r */=0A+ case 4: /* tzmsk = r/m,r */=0A+ case 5: /* blcic r/m,r */=0A+ case 6: /* blsic = r/m,r */=0A+ case 7: /* t1mskc r/m,r */=0A+ host_and_vcpu= _must_have(tbm);=0A+ break;=0A+ default:=0A+ = goto cannot_emulate;=0A+ }=0A+=0A+ xop_09_rm_rv:=0A+ {=0A+ = uint8_t *buf =3D get_stub(stub);=0A+ typeof(vex) *pxop =3D = container_of(buf + 1, typeof(vex), raw[0]);=0A+=0A+ generate_excepti= on_if(vex.l, EXC_UD);=0A+=0A+ buf[0] =3D 0x8f;=0A+ *pxop =3D = vex;=0A+ pxop->b =3D 1;=0A+ pxop->r =3D 1;=0A+ = pxop->reg =3D ~0; /* rAX */=0A+ buf[3] =3D b;=0A+ buf[4] =3D = (modrm & 0x38) | 0x01; /* r/m=3D(%rCX) */=0A+ buf[5] =3D = 0xc3;=0A+=0A+ dst.reg =3D decode_register(~vex.reg & (mode_64bit() = ? 0xf : 7),=0A+ &_regs, 0);=0A+ = emulate_stub([dst] "=3D&a" (dst.val), "c" (&src.val));=0A+=0A+ = put_stub(stub);=0A+ break;=0A+ }=0A+=0A+ case X86EMUL_OPC(0x8f= 09, 0x02): /* XOP Grp2 */=0A+ switch ( modrm_reg & 7 )=0A+ = {=0A+ case 1: /* blcmsk r/m,r */=0A+ case 6: /* blci r/m,r = */=0A+ host_and_vcpu_must_have(tbm);=0A+ goto = xop_09_rm_rv;=0A+ }=0A+ goto cannot_emulate;=0A+=0A+ case = X86EMUL_OPC(0x8f0a, 0x10): /* bextr imm,r/m,r */=0A+ {=0A+ = uint8_t *buf =3D get_stub(stub);=0A+ typeof(vex) *pxop =3D = container_of(buf + 1, typeof(vex), raw[0]);=0A+=0A+ host_and_vcpu_mu= st_have(tbm);=0A+ generate_exception_if(vex.l || vex.reg !=3D 0xf, = EXC_UD);=0A+=0A+ if ( ea.type =3D=3D OP_REG )=0A+ = src.val =3D *ea.reg;=0A+ else if ( (rc =3D read_ulong(ea.mem.seg, = ea.mem.off, &src.val, op_bytes,=0A+ = ctxt, ops)) !=3D X86EMUL_OKAY )=0A+ goto done;=0A+=0A+ = buf[0] =3D 0x8f;=0A+ *pxop =3D vex;=0A+ pxop->b =3D 1;=0A+ = pxop->r =3D 1;=0A+ buf[3] =3D b;=0A+ buf[4] =3D 0x09; = /* reg=3DrCX r/m=3D(%rCX) */=0A+ *(uint32_t *)(buf + 5) =3D = imm1;=0A+ buf[9] =3D 0xc3;=0A+=0A+ emulate_stub([dst] = "=3D&c" (dst.val), "[dst]" (&src.val));=0A+=0A+ put_stub(stub);=0A+ = break;=0A+ }=0A+=0A default:=0A goto cannot_emulate;= =0A }=0A--- a/xen/include/asm-x86/cpufeature.h=0A+++ b/xen/include/asm-= x86/cpufeature.h=0A@@ -74,6 +74,7 @@=0A #define cpu_has_eist = boot_cpu_has(X86_FEATURE_EIST)=0A #define cpu_has_hypervisor boot_cpu_ha= s(X86_FEATURE_HYPERVISOR)=0A #define cpu_has_cmp_legacy boot_cpu_has(X86_FE= ATURE_CMP_LEGACY)=0A+#define cpu_has_tbm boot_cpu_has(X86_FE= ATURE_TBM)=0A =0A enum _cache_type {=0A CACHE_TYPE_NULL =3D 0,=0A --=__Part8AB3A731.1__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwczovL2xpc3RzLnhlbi5v cmcveGVuLWRldmVsCg== --=__Part8AB3A731.1__=--