There's room for speeding up emulation of invalid guest state. Let's
track our progress by adding a few small performance tests.
Current results on a Xeon E5 (Sandy Bridge) with unrestricted_guest=0:
739 cycles/emulated jump instruction
925 cycles/emulated move instruction
887 cycles/emulated arithmetic instruction
916 cycles/emulated memory load instruction
1109 cycles/emulated memory RMW instruction
Signed-off-by: Paolo Bonzini <[email protected]>
---
v1->v2: rewritten, added more tests
x86/realmode.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 96 insertions(+)
diff --git a/x86/realmode.c b/x86/realmode.c
index ae91b9e..d851d51 100644
--- a/x86/realmode.c
+++ b/x86/realmode.c
@@ -91,6 +91,18 @@ static void print_serial(const char *buf)
#endif
}
+static void print_serial_u32(u32 value)
+{
+ char n[12], *p;
+ p = &n[11];
+ *p = 0;
+ do {
+ *--p = '0' + (value % 10);
+ value /= 10;
+ } while (value > 0);
+ print_serial(p);
+}
+
static void exit(int code)
{
outb(code, 0xf4);
@@ -1534,6 +1546,85 @@ static void test_nopl(void)
report("nopl", 0, 1);
}
+static u32 perf_baseline;
+
+#define PERF_COUNT 100000
+
+#define MK_INSN_PERF(name, insn) \
+ MK_INSN(name, "rdtsc; mov %eax, %ebx; mov %edx, %esi\n" \
+ "1:" insn "\n" \
+ "loop 1b\n" \
+ "rdtsc");
+
+static u32 cycles_in_big_real_mode(struct insn_desc *insn)
+{
+ u64 start, end;
+
+ inregs.ecx = PERF_COUNT;
+ exec_in_big_real_mode(insn);
+ start = ((u64)outregs.esi << 32) | outregs.ebx;
+ end = ((u64)outregs.edx << 32) | outregs.eax;
+
+ return end - start;
+}
+
+static void test_perf_loop(void)
+{
+ /*
+ * This test runs simple instructions that should roughly take the
+ * same time to emulate: 1000 iterations of "loop" and 3 setup
+ * instructions. Other performance tests can run PERF_COUNT
+ * iterations of the same instruction and subtract the cycle count
+ * of this test.
+ */
+ MK_INSN_PERF(perf_loop, "");
+ perf_baseline = cycles_in_big_real_mode(&insn_perf_loop);
+ print_serial_u32(perf_baseline / (PERF_COUNT + 3));
+ print_serial(" cycles/emulated jump instruction\n");
+}
+
+static void test_perf_mov(void)
+{
+ u32 cyc;
+
+ MK_INSN_PERF(perf_move, "mov %esi, %edi");
+ cyc = cycles_in_big_real_mode(&insn_perf_move);
+ print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
+ print_serial(" cycles/emulated move instruction\n");
+}
+
+static void test_perf_arith(void)
+{
+ u32 cyc;
+
+ MK_INSN_PERF(perf_arith, "add $4, %edi");
+ cyc = cycles_in_big_real_mode(&insn_perf_arith);
+ print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
+ print_serial(" cycles/emulated arithmetic instruction\n");
+}
+
+static void test_perf_memory_load(void)
+{
+ u32 cyc, tmp;
+
+ MK_INSN_PERF(perf_memory_load, "cmp $0, (%edi)");
+ inregs.edi = (u32)&tmp;
+ cyc = cycles_in_big_real_mode(&insn_perf_memory_load);
+ print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
+ print_serial(" cycles/emulated memory load instruction\n");
+}
+
+static void test_perf_memory_rmw(void)
+{
+ u32 cyc, tmp;
+
+ MK_INSN_PERF(perf_memory_rmw, "add $1, (%edi)");
+ inregs.edi = (u32)&tmp;
+ cyc = cycles_in_big_real_mode(&insn_perf_memory_rmw);
+ print_serial_u32((cyc - perf_baseline) / PERF_COUNT);
+ print_serial(" cycles/emulated memory RMW instruction\n");
+}
+
void realmode_start(void)
{
test_null();
@@ -1580,6 +1671,11 @@ void realmode_start(void)
test_salc();
test_fninit();
test_nopl();
+ test_perf_loop();
+ test_perf_mov();
+ test_perf_arith();
+ test_perf_memory_load();
+ test_perf_memory_rmw();
exit(0);
}
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html