From 4ae2533d2c322ad93eb471a2e55c7adad3b85aef Mon Sep 17 00:00:00 2001 From: Yixun Lan Date: Sat, 13 Sep 2014 22:38:14 +0800 Subject: [PATCH] Revert "x86_emulate: properly do IP updates and other side effects on success" This reverts commit 91a13bcf99d1a47f6f7ccd364b95b1b8500c2be2. --- tools/tests/x86_emulator/test_x86_emulator.c | 140 +++++++++++++-------------- xen/arch/x86/x86_emulate/x86_emulate.c | 33 ++++--- 2 files changed, 87 insertions(+), 86 deletions(-) diff --git a/tools/tests/x86_emulator/test_x86_emulator.c b/tools/tests/x86_emulator/test_x86_emulator.c index 3166674..7404ee3 100644 --- a/tools/tests/x86_emulator/test_x86_emulator.c +++ b/tools/tests/x86_emulator/test_x86_emulator.c @@ -597,32 +597,23 @@ int main(int argc, char **argv) printf("skipped\n"); #endif -#define decl_insn(which) extern const unsigned char which[], which##_len[] -#define put_insn(which, insn) ".pushsection .test, \"ax\", @progbits\n" \ - #which ": " insn "\n" \ - ".equ " #which "_len, .-" #which "\n" \ - ".popsection" -#define set_insn(which) (regs.eip = (unsigned long)memcpy(instr, which, \ - (unsigned long)which##_len)) -#define check_eip(which) (regs.eip == (unsigned long)instr + \ - (unsigned long)which##_len) - printf("%-40s", "Testing movq %mm3,(%ecx)..."); if ( stack_exec && cpu_has_mmx ) { - decl_insn(movq_to_mem); + extern const unsigned char movq_to_mem[]; asm volatile ( "pcmpeqb %%mm3, %%mm3\n" - put_insn(movq_to_mem, "movq %%mm3, (%0)") - :: "c" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "movq_to_mem: movq %%mm3, (%0)\n" + ".popsection" :: "c" (NULL) ); - set_insn(movq_to_mem); + memcpy(instr, movq_to_mem, 15); memset(res, 0x33, 64); memset(res + 8, 0xff, 8); + regs.eip = (unsigned long)&instr[0]; regs.ecx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 8, 32) || - !check_eip(movq_to_mem) ) + if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 8, 32) ) goto fail; printf("okay\n"); } @@ -632,17 +623,19 @@ int main(int argc, char **argv) printf("%-40s", "Testing movq (%edx),%mm5..."); if ( stack_exec && cpu_has_mmx ) { - decl_insn(movq_from_mem); + extern const unsigned char movq_from_mem[]; asm volatile ( "pcmpgtb %%mm5, %%mm5\n" - put_insn(movq_from_mem, "movq (%0), %%mm5") - :: "d" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "movq_from_mem: movq (%0), %%mm5\n" + ".popsection" :: "d" (NULL) ); - set_insn(movq_from_mem); + memcpy(instr, movq_from_mem, 15); + regs.eip = (unsigned long)&instr[0]; regs.ecx = 0; regs.edx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( rc != X86EMUL_OKAY || !check_eip(movq_from_mem) ) + if ( rc != X86EMUL_OKAY ) goto fail; asm ( "pcmpeqb %%mm3, %%mm3\n\t" "pcmpeqb %%mm5, %%mm3\n\t" @@ -657,19 +650,20 @@ int main(int argc, char **argv) printf("%-40s", "Testing movdqu %xmm2,(%ecx)..."); if ( stack_exec && cpu_has_sse2 ) { - decl_insn(movdqu_to_mem); + extern const unsigned char movdqu_to_mem[]; asm volatile ( "pcmpeqb %%xmm2, %%xmm2\n" - put_insn(movdqu_to_mem, "movdqu %%xmm2, (%0)") - :: "c" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "movdqu_to_mem: movdqu %%xmm2, (%0)\n" + ".popsection" :: "c" (NULL) ); - set_insn(movdqu_to_mem); + memcpy(instr, movdqu_to_mem, 15); memset(res, 0x55, 64); memset(res + 8, 0xff, 16); + regs.eip = (unsigned long)&instr[0]; regs.ecx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 8, 32) || - !check_eip(movdqu_to_mem) ) + if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 8, 32) ) goto fail; printf("okay\n"); } @@ -679,17 +673,19 @@ int main(int argc, char **argv) printf("%-40s", "Testing movdqu (%edx),%xmm4..."); if ( stack_exec && cpu_has_sse2 ) { - decl_insn(movdqu_from_mem); + extern const unsigned char movdqu_from_mem[]; asm volatile ( "pcmpgtb %%xmm4, %%xmm4\n" - put_insn(movdqu_from_mem, "movdqu (%0), %%xmm4") - :: "d" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "movdqu_from_mem: movdqu (%0), %%xmm4\n" + ".popsection" :: "d" (NULL) ); - set_insn(movdqu_from_mem); + memcpy(instr, movdqu_from_mem, 15); + regs.eip = (unsigned long)&instr[0]; regs.ecx = 0; regs.edx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( rc != X86EMUL_OKAY || !check_eip(movdqu_from_mem) ) + if ( rc != X86EMUL_OKAY ) goto fail; asm ( "pcmpeqb %%xmm2, %%xmm2\n\t" "pcmpeqb %%xmm4, %%xmm2\n\t" @@ -704,20 +700,21 @@ int main(int argc, char **argv) printf("%-40s", "Testing vmovdqu %ymm2,(%ecx)..."); if ( stack_exec && cpu_has_avx ) { - decl_insn(vmovdqu_to_mem); + extern const unsigned char vmovdqu_to_mem[]; asm volatile ( "vpcmpeqb %%xmm2, %%xmm2, %%xmm2\n" - put_insn(vmovdqu_to_mem, "vmovdqu %%ymm2, (%0)") - :: "c" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "vmovdqu_to_mem: vmovdqu %%ymm2, (%0)\n" + ".popsection" :: "c" (NULL) ); - set_insn(vmovdqu_to_mem); + memcpy(instr, vmovdqu_to_mem, 15); memset(res, 0x55, 128); memset(res + 16, 0xff, 16); memset(res + 20, 0x00, 16); + regs.eip = (unsigned long)&instr[0]; regs.ecx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 16, 64) || - !check_eip(vmovdqu_to_mem) ) + if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 16, 64) ) goto fail; printf("okay\n"); } @@ -727,7 +724,7 @@ int main(int argc, char **argv) printf("%-40s", "Testing vmovdqu (%edx),%ymm4..."); if ( stack_exec && cpu_has_avx ) { - decl_insn(vmovdqu_from_mem); + extern const unsigned char vmovdqu_from_mem[]; #if 0 /* Don't use AVX2 instructions for now */ asm volatile ( "vpcmpgtb %%ymm4, %%ymm4, %%ymm4\n" @@ -735,15 +732,17 @@ int main(int argc, char **argv) asm volatile ( "vpcmpgtb %%xmm4, %%xmm4, %%xmm4\n\t" "vinsertf128 $1, %%xmm4, %%ymm4, %%ymm4\n" #endif - put_insn(vmovdqu_from_mem, "vmovdqu (%0), %%ymm4") - :: "d" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "vmovdqu_from_mem: vmovdqu (%0), %%ymm4\n" + ".popsection" :: "d" (NULL) ); - set_insn(vmovdqu_from_mem); + memcpy(instr, vmovdqu_from_mem, 15); memset(res + 4, 0xff, 16); + regs.eip = (unsigned long)&instr[0]; regs.ecx = 0; regs.edx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( rc != X86EMUL_OKAY || !check_eip(vmovdqu_from_mem) ) + if ( rc != X86EMUL_OKAY ) goto fail; #if 0 /* Don't use AVX2 instructions for now */ asm ( "vpcmpeqb %%ymm2, %%ymm2, %%ymm2\n\t" @@ -770,19 +769,20 @@ int main(int argc, char **argv) memset(res + 10, 0x66, 8); if ( stack_exec && cpu_has_sse2 ) { - decl_insn(movsd_to_mem); + extern const unsigned char movsd_to_mem[]; asm volatile ( "movlpd %0, %%xmm5\n\t" "movhpd %0, %%xmm5\n" - put_insn(movsd_to_mem, "movsd %%xmm5, (%1)") - :: "m" (res[10]), "c" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "movsd_to_mem: movsd %%xmm5, (%1)\n" + ".popsection" :: "m" (res[10]), "c" (NULL) ); - set_insn(movsd_to_mem); + memcpy(instr, movsd_to_mem, 15); + regs.eip = (unsigned long)&instr[0]; regs.ecx = (unsigned long)(res + 2); regs.edx = 0; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 8, 32) || - !check_eip(movsd_to_mem) ) + if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 8, 32) ) goto fail; printf("okay\n"); } @@ -795,17 +795,19 @@ int main(int argc, char **argv) printf("%-40s", "Testing movaps (%edx),%xmm7..."); if ( stack_exec && cpu_has_sse ) { - decl_insn(movaps_from_mem); + extern const unsigned char movaps_from_mem[]; asm volatile ( "xorps %%xmm7, %%xmm7\n" - put_insn(movaps_from_mem, "movaps (%0), %%xmm7") - :: "d" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "movaps_from_mem: movaps (%0), %%xmm7\n" + ".popsection" :: "d" (NULL) ); - set_insn(movaps_from_mem); + memcpy(instr, movaps_from_mem, 15); + regs.eip = (unsigned long)&instr[0]; regs.ecx = 0; regs.edx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( rc != X86EMUL_OKAY || !check_eip(movaps_from_mem) ) + if ( rc != X86EMUL_OKAY ) goto fail; asm ( "cmpeqps %1, %%xmm7\n\t" "movmskps %%xmm7, %0" : "=r" (rc) : "m" (res[8]) ); @@ -821,18 +823,19 @@ int main(int argc, char **argv) memset(res + 10, 0x77, 8); if ( stack_exec && cpu_has_avx ) { - decl_insn(vmovsd_to_mem); + extern const unsigned char vmovsd_to_mem[]; asm volatile ( "vbroadcastsd %0, %%ymm5\n" - put_insn(vmovsd_to_mem, "vmovsd %%xmm5, (%1)") - :: "m" (res[10]), "c" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "vmovsd_to_mem: vmovsd %%xmm5, (%1)\n" + ".popsection" :: "m" (res[10]), "c" (NULL) ); - set_insn(vmovsd_to_mem); + memcpy(instr, vmovsd_to_mem, 15); + regs.eip = (unsigned long)&instr[0]; regs.ecx = (unsigned long)(res + 2); regs.edx = 0; rc = x86_emulate(&ctxt, &emulops); - if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 8, 32) || - !check_eip(vmovsd_to_mem) ) + if ( (rc != X86EMUL_OKAY) || memcmp(res, res + 8, 32) ) goto fail; printf("okay\n"); } @@ -845,17 +848,19 @@ int main(int argc, char **argv) printf("%-40s", "Testing vmovaps (%edx),%ymm7..."); if ( stack_exec && cpu_has_avx ) { - decl_insn(vmovaps_from_mem); + extern const unsigned char vmovaps_from_mem[]; asm volatile ( "vxorps %%ymm7, %%ymm7, %%ymm7\n" - put_insn(vmovaps_from_mem, "vmovaps (%0), %%ymm7") - :: "d" (NULL) ); + ".pushsection .test, \"a\", @progbits\n" + "vmovaps_from_mem: vmovaps (%0), %%ymm7\n" + ".popsection" :: "d" (NULL) ); - set_insn(vmovaps_from_mem); + memcpy(instr, vmovaps_from_mem, 15); + regs.eip = (unsigned long)&instr[0]; regs.ecx = 0; regs.edx = (unsigned long)res; rc = x86_emulate(&ctxt, &emulops); - if ( rc != X86EMUL_OKAY || !check_eip(vmovaps_from_mem) ) + if ( rc != X86EMUL_OKAY ) goto fail; asm ( "vcmpeqps %1, %%ymm7, %%ymm0\n\t" "vmovmskps %%ymm0, %0" : "=r" (rc) : "m" (res[8]) ); @@ -866,11 +871,6 @@ int main(int argc, char **argv) else printf("skipped\n"); -#undef decl_insn -#undef put_insn -#undef set_insn -#undef check_eip - for ( j = 1; j <= 2; j++ ) { #if defined(__i386__) diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index 50d8965..e833cdf 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -720,26 +720,29 @@ do{ uint8_t stub[] = { _bytes, 0xc3 }; \ put_fpu(&fic); \ } while (0) -static unsigned long _get_rep_prefix( - const struct cpu_user_regs *int_regs, +static unsigned long __get_rep_prefix( + struct cpu_user_regs *int_regs, + struct cpu_user_regs *ext_regs, int ad_bytes) { - return (ad_bytes == 2) ? (uint16_t)int_regs->ecx : - (ad_bytes == 4) ? (uint32_t)int_regs->ecx : - int_regs->ecx; + unsigned long ecx = ((ad_bytes == 2) ? (uint16_t)int_regs->ecx : + (ad_bytes == 4) ? (uint32_t)int_regs->ecx : + int_regs->ecx); + + /* Skip the instruction if no repetitions are required. */ + if ( ecx == 0 ) + ext_regs->eip = int_regs->eip; + + return ecx; } #define get_rep_prefix() ({ \ unsigned long max_reps = 1; \ if ( rep_prefix() ) \ - max_reps = _get_rep_prefix(&_regs, ad_bytes); \ + max_reps = __get_rep_prefix(&_regs, ctxt->regs, ad_bytes); \ if ( max_reps == 0 ) \ - { \ - /* Skip the instruction if no repetitions are required. */ \ - dst.type = OP_NONE; \ - goto writeback; \ - } \ - max_reps; \ + goto done; \ + max_reps; \ }) static void __put_rep_prefix( @@ -3918,8 +3921,7 @@ x86_emulate( if ( !rc && (b & 1) && (ea.type == OP_MEM) ) rc = ops->write(ea.mem.seg, ea.mem.off, mmvalp, ea.bytes, ctxt); - dst.type = OP_NONE; - break; + goto done; } case 0x20: /* mov cr,reg */ @@ -4186,8 +4188,7 @@ x86_emulate( if ( !rc && (b != 0x6f) && (ea.type == OP_MEM) ) rc = ops->write(ea.mem.seg, ea.mem.off, mmvalp, ea.bytes, ctxt); - dst.type = OP_NONE; - break; + goto done; } case 0x80 ... 0x8f: /* jcc (near) */ { -- 1.9.3