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 <pbonzini@xxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html