2014-06-18 14:20:14

by Nadav Amit

[permalink] [raw]
Subject: [PATCH kvm-unit-tests 0/5] x86: Tests for recent emulator bugs

This patch-set checks recent emulator bugs as well as monitor-mwait emulation
in real-mode.

Nadav Amit (5):
x86: Testing nop instruction on 64-bit
x86: test xadd with two identical operands
x86: Test btcq with operand larger than 64
x86: check cmov instruction on 64-bit
x86: Test monitor and mwait on real-mode

x86/emulator.c | 30 ++++++++++++++++++++++++++++--
x86/realmode.c | 20 ++++++++++++++++++++
2 files changed, 48 insertions(+), 2 deletions(-)

--
1.9.1


2014-06-18 14:20:11

by Nadav Amit

[permalink] [raw]
Subject: [PATCH kvm-unit-tests 4/5] x86: check cmov instruction on 64-bit

cmov instruction on 64-bit with dword destination register operand should clear
bits [63:32]. This test checks this behavior due to previous KVM bug.

Signed-off-by: Nadav Amit <[email protected]>
---
x86/emulator.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/x86/emulator.c b/x86/emulator.c
index 460949f..1fd0ca6 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -710,6 +710,18 @@ static void test_shld_shrd(u32 *mem)
report("shrd (cl)", *mem == ((0x12345678 >> 3) | (5u << 29)));
}

+static void test_cmov(u32 *mem)
+{
+ u64 val;
+ *mem = 0xabcdef12u;
+ asm ("movq $0x1234567812345678, %%rax\n\t"
+ "cmpl %%eax, %%eax\n\t"
+ "cmovnel (%[mem]), %%eax\n\t"
+ "movq %%rax, %[val]\n\t"
+ : [val]"=r"(val) : [mem]"r"(mem) : "%rax", "cc");
+ report("cmovnel", val == 0x12345678ul);
+}
+
#define INSN_XCHG_ALL \
"xchg %rax, 0+save \n\t" \
"xchg %rbx, 8+save \n\t" \
@@ -1054,12 +1066,12 @@ int main()
test_sreg(mem);
test_lldt(mem);
test_ltr(mem);
+ test_cmov(mem);

test_mmx_movq_mf(mem, insn_page, alt_insn_page, insn_ram);
test_movabs(mem, insn_page, alt_insn_page, insn_ram);
test_smsw_reg(mem, insn_page, alt_insn_page, insn_ram);
test_nop(mem, insn_page, alt_insn_page, insn_ram);
-
test_crosspage_mmio(mem);

test_string_io_mmio(mem);
--
1.9.1

2014-06-18 14:20:08

by Nadav Amit

[permalink] [raw]
Subject: [PATCH kvm-unit-tests 1/5] x86: Testing nop instruction on 64-bit

Previously, nop instruction emulation on 64-bit caused RAX bits [63:32] to be
cleared. This test checks the behavior is correct and RAX is unmodified.

Signed-off-by: Nadav Amit <[email protected]>
---
x86/emulator.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/x86/emulator.c b/x86/emulator.c
index f653127..bf8a873 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -845,6 +845,15 @@ static void test_smsw_reg(uint64_t *mem, uint8_t *insn_page,
report("64-bit smsw reg", outregs.rax == cr0);
}

+static void test_nop(uint64_t *mem, uint8_t *insn_page,
+ uint8_t *alt_insn_page, void *insn_ram)
+{
+ inregs = (struct regs){ .rax = 0x1234567890abcdeful };
+ MK_INSN(nop, "nop\n\t");
+ trap_emulator(mem, alt_insn_page, &insn_nop);
+ report("nop", outregs.rax == inregs.rax);
+}
+
static void test_crosspage_mmio(volatile uint8_t *mem)
{
volatile uint16_t w, *pw;
@@ -1045,6 +1054,7 @@ int main()
test_mmx_movq_mf(mem, insn_page, alt_insn_page, insn_ram);
test_movabs(mem, insn_page, alt_insn_page, insn_ram);
test_smsw_reg(mem, insn_page, alt_insn_page, insn_ram);
+ test_nop(mem, insn_page, alt_insn_page, insn_ram);

test_crosspage_mmio(mem);

--
1.9.1

2014-06-18 14:21:10

by Nadav Amit

[permalink] [raw]
Subject: [PATCH kvm-unit-tests 5/5] x86: Test monitor and mwait on real-mode

monitor and mwait are now considered to behave as nop. New patch enables
monitor and mwait in realmode as well. This test checks whether they are
handled as nop in realmode as well.

Signed-off-by: Nadav Amit <[email protected]>
---
x86/realmode.c | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/x86/realmode.c b/x86/realmode.c
index 10c3e03..0a62b5d 100644
--- a/x86/realmode.c
+++ b/x86/realmode.c
@@ -1671,6 +1671,16 @@ void test_xadd(void)
report("xadd", R_AX, outregs.eax == inregs.eax * 2);
}

+void test_monitor_mwait(void)
+{
+ MK_INSN(monitor, "monitor\n\t"
+ "mwait\n\t");
+ inregs.ecx = 0;
+ inregs.eax = 0;
+ exec_in_big_real_mode(&insn_monitor);
+ report("monitor", 0, 1);
+}
+

void realmode_start(void)
{
@@ -1721,6 +1731,7 @@ void realmode_start(void)
test_smsw();
test_nopl();
test_xadd();
+ test_monitor_mwait();
test_perf_loop();
test_perf_mov();
test_perf_arith();
--
1.9.1

2014-06-18 14:21:39

by Nadav Amit

[permalink] [raw]
Subject: [PATCH kvm-unit-tests 2/5] x86: test xadd with two identical operands

Previously, KVM emulated xadd incorrectly when the source and destination
operands were identical. The expected result is that the register would hold
the sum (2x) and not the previous value (x). This test checks this behavior.
It should be executed with a disabled unrestricted mode.

Signed-off-by: Nadav Amit <[email protected]>
---
x86/realmode.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/x86/realmode.c b/x86/realmode.c
index dc4a1d3..10c3e03 100644
--- a/x86/realmode.c
+++ b/x86/realmode.c
@@ -1663,6 +1663,14 @@ void test_smsw(void)
report("smsw", R_AX | R_BX | R_CX, outregs.eax == outregs.ebx);
}

+void test_xadd(void)
+{
+ MK_INSN(xadd, "xaddl %eax, %eax\n\t");
+ inregs.eax = 0x12345678;
+ exec_in_big_real_mode(&insn_xadd);
+ report("xadd", R_AX, outregs.eax == inregs.eax * 2);
+}
+

void realmode_start(void)
{
@@ -1712,6 +1720,7 @@ void realmode_start(void)
test_dr_mod();
test_smsw();
test_nopl();
+ test_xadd();
test_perf_loop();
test_perf_mov();
test_perf_arith();
--
1.9.1

2014-06-18 14:21:38

by Nadav Amit

[permalink] [raw]
Subject: [PATCH kvm-unit-tests 3/5] x86: Test btcq with operand larger than 64

Previously, KVM did not calculate the offset for bit-operations correctly when
quad-word operands were used. This test checks btcq when operand is larger
than 64 in order to check this scenario.

Signed-off-by: Nadav Amit <[email protected]>
---
x86/emulator.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/x86/emulator.c b/x86/emulator.c
index bf8a873..460949f 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -496,7 +496,7 @@ void test_btc(void *mem)
{
unsigned int *a = mem;

- memset(mem, 0, 3 * sizeof(unsigned int));
+ memset(mem, 0, 4 * sizeof(unsigned int));

asm ("btcl $32, %0" :: "m"(a[0]) : "memory");
asm ("btcl $1, %0" :: "m"(a[1]) : "memory");
@@ -505,6 +505,10 @@ void test_btc(void *mem)

asm ("btcl %1, %0" :: "m"(a[3]), "r"(-1) : "memory");
report("btcl reg, r/m", a[0] == 1 && a[1] == 2 && a[2] == 0x80000004);
+
+ asm ("btcq %1, %0" : : "m"(a[2]), "r"(-1l) : "memory");
+ report("btcq reg, r/m", a[0] == 1 && a[1] == 0x80000002 &&
+ a[2] == 0x80000004 && a[3] == 0);
}

void test_bsfbsr(void *mem)
--
1.9.1