KVM: x86: Fix zero iterations REP-string
authorNadav Amit <namit@cs.technion.ac.il>
Tue, 28 Apr 2015 10:06:01 +0000 (13:06 +0300)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 19 May 2015 18:52:36 +0000 (20:52 +0200)
commit428e3d08574b77876ea5e71f294f91bd8afa51b5
tree88b926274e851fc4919468fdd24a30ca52086b2f
parentee122a7109e42313caadf6038ab773d1f68fcce1
KVM: x86: Fix zero iterations REP-string

When a REP-string is executed in 64-bit mode with an address-size prefix,
ECX/EDI/ESI are used as counter and pointers. When ECX is initially zero, Intel
CPUs clear the high 32-bits of RCX, and recent Intel CPUs update the high bits
of the pointers in MOVS/STOS. This behavior is specific to Intel according to
few experiments.

As one may guess, this is an undocumented behavior. Yet, it is observable in
the guest, since at least VMX traps REP-INS/OUTS even when ECX=0. Note that
VMware appears to get it right.  The behavior can be observed using the
following code:

 #include <stdio.h>

 #define LOW_MASK (0xffffffff00000000ull)
 #define ALL_MASK (0xffffffffffffffffull)
 #define TEST(opcode) \
do { \
asm volatile(".byte 0xf2 \n\t .byte 0x67 \n\t .byte " opcode "\n\t" \
: "=S"(s), "=c"(c), "=D"(d)  \
: "S"(ALL_MASK), "c"(LOW_MASK), "D"(ALL_MASK)); \
printf("opcode %s rcx=%llx rsi=%llx rdi=%llx\n", \
opcode, c, s, d); \
} while(0)

void main()
{
unsigned long long s, d, c;
iopl(3);
TEST("0x6c");
TEST("0x6d");
TEST("0x6e");
TEST("0x6f");
TEST("0xa4");
TEST("0xa5");
TEST("0xa6");
TEST("0xa7");
TEST("0xaa");
TEST("0xab");
TEST("0xae");
TEST("0xaf");
}

Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/emulate.c