|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] x86emul: support POPCNT
commit f88e810cc130d919dc69dfb1e632a602c9d10823
Author: Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Jan 17 10:32:54 2017 +0100
Commit: Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Jan 17 10:32:54 2017 +0100
x86emul: support POPCNT
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
tools/tests/x86_emulator/test_x86_emulator.c | 46 ++++++++++++++++++++++++++++
tools/tests/x86_emulator/x86_emulate.h | 6 ++++
xen/arch/x86/x86_emulate/x86_emulate.c | 15 ++++++++-
xen/include/asm-x86/cpufeature.h | 1 +
4 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/tools/tests/x86_emulator/test_x86_emulator.c
b/tools/tests/x86_emulator/test_x86_emulator.c
index 0d5655a..1cd3581 100644
--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -684,6 +684,52 @@ int main(int argc, char **argv)
goto fail;
printf("okay\n");
+ printf("%-40s", "Testing popcnt (%edx),%cx...");
+ if ( cpu_has_popcnt )
+ {
+ instr[0] = 0x66; instr[1] = 0xf3;
+ instr[2] = 0x0f; instr[3] = 0xb8; instr[4] = 0x0a;
+
+ *res = 0xfedcba98;
+ regs.edx = (unsigned long)res;
+ regs.eflags = 0xac3;
+ regs.eip = (unsigned long)&instr[0];
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( (rc != X86EMUL_OKAY) || (uint16_t)regs.ecx != 8 || *res !=
0xfedcba98 ||
+ (regs.eflags & 0xfeb) != 0x202 ||
+ (regs.eip != (unsigned long)&instr[5]) )
+ goto fail;
+ printf("okay\n");
+
+ printf("%-40s", "Testing popcnt (%edx),%ecx...");
+ regs.eflags = 0xac3;
+ regs.eip = (unsigned long)&instr[1];
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( (rc != X86EMUL_OKAY) || regs.ecx != 20 || *res != 0xfedcba98 ||
+ (regs.eflags & 0xfeb) != 0x202 ||
+ (regs.eip != (unsigned long)&instr[5]) )
+ goto fail;
+ printf("okay\n");
+
+#ifdef __x86_64__
+ printf("%-40s", "Testing popcnt (%rdx),%rcx...");
+ instr[0] = 0xf3;
+ instr[1] = 0x48;
+ res[1] = 0x12345678;
+ regs.eflags = 0xac3;
+ regs.eip = (unsigned long)&instr[0];
+ rc = x86_emulate(&ctxt, &emulops);
+ if ( (rc != X86EMUL_OKAY) || regs.ecx != 33 ||
+ res[0] != 0xfedcba98 || res[1] != 0x12345678 ||
+ (regs.eflags & 0xfeb) != 0x202 ||
+ (regs.eip != (unsigned long)&instr[5]) )
+ goto fail;
+ printf("okay\n");
+#endif
+ }
+ else
+ printf("skipped\n");
+
printf("%-40s", "Testing lar (null selector)...");
instr[0] = 0x0f; instr[1] = 0x02; instr[2] = 0xc1;
regs.eflags = 0x240;
diff --git a/tools/tests/x86_emulator/x86_emulate.h
b/tools/tests/x86_emulator/x86_emulate.h
index 8bc2e43..596d55a 100644
--- a/tools/tests/x86_emulator/x86_emulate.h
+++ b/tools/tests/x86_emulator/x86_emulate.h
@@ -81,6 +81,12 @@ static inline uint64_t xgetbv(uint32_t xcr)
(res.d & (1U << 26)) != 0; \
})
+#define cpu_has_popcnt ({ \
+ struct cpuid_leaf res; \
+ emul_test_cpuid(1, 0, &res, NULL); \
+ (res.c & (1U << 23)) != 0; \
+})
+
#define cpu_has_xsave ({ \
struct cpuid_leaf res; \
emul_test_cpuid(1, 0, &res, NULL); \
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c
b/xen/arch/x86/x86_emulate/x86_emulate.c
index 20285b2..6d6c53d 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1335,6 +1335,7 @@ static bool vcpu_has(
#define vcpu_has_cx16() vcpu_has( 1, ECX, 13, ctxt, ops)
#define vcpu_has_sse4_2() vcpu_has( 1, ECX, 20, ctxt, ops)
#define vcpu_has_movbe() vcpu_has( 1, ECX, 22, ctxt, ops)
+#define vcpu_has_popcnt() vcpu_has( 1, ECX, 23, ctxt, ops)
#define vcpu_has_avx() vcpu_has( 1, ECX, 28, ctxt, ops)
#define vcpu_has_lahf_lm() vcpu_has(0x80000001, ECX, 0, ctxt, ops)
#define vcpu_has_cr8_legacy() vcpu_has(0x80000001, ECX, 4, ctxt, ops)
@@ -2103,8 +2104,12 @@ x86_decode_twobyte(
op_bytes = mode_64bit() ? 8 : 4;
break;
+ case 0xb8: /* jmpe / popcnt */
+ if ( rep_prefix() )
+ ctxt->opcode |= MASK_INSR(vex.pfx, X86EMUL_OPC_PFX_MASK);
+ break;
+
/* Intentionally not handling here despite being modified by F3:
- case 0xb8: jmpe / popcnt
case 0xbc: bsf / tzcnt
case 0xbd: bsr / lzcnt
* They're being dealt with in the execution phase (if at all).
@@ -5614,6 +5619,14 @@ x86_emulate(
dst.val = (uint16_t)src.val;
break;
+ case X86EMUL_OPC_F3(0x0f, 0xb8): /* popcnt r/m,r */
+ host_and_vcpu_must_have(popcnt);
+ asm ( "popcnt %1,%0" : "=r" (dst.val) : "rm" (src.val) );
+ _regs._eflags &= ~EFLAGS_MASK;
+ if ( !dst.val )
+ _regs._eflags |= EFLG_ZF;
+ break;
+
case X86EMUL_OPC(0x0f, 0xba): /* Grp8 */
switch ( modrm_reg & 7 )
{
diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h
index f34d01c..ba1c5e5 100644
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -40,6 +40,7 @@
#define cpu_has_mmx 1
#define cpu_has_sse3 boot_cpu_has(X86_FEATURE_SSE3)
#define cpu_has_sse4_2 boot_cpu_has(X86_FEATURE_SSE4_2)
+#define cpu_has_popcnt boot_cpu_has(X86_FEATURE_POPCNT)
#define cpu_has_htt boot_cpu_has(X86_FEATURE_HTT)
#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX)
#define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLUSH)
--
generated by git-patchbot for /home/xen/git/xen.git#master
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |