Signed-off-by: Avi Kivity <a...@redhat.com> --- config-x86-common.mak | 4 ++- x86/pmu.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletions(-) create mode 100644 x86/pmu.c
diff --git a/config-x86-common.mak b/config-x86-common.mak index 033bae0..7932b5c 100644 --- a/config-x86-common.mak +++ b/config-x86-common.mak @@ -34,7 +34,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \ $(TEST_DIR)/realmode.flat $(TEST_DIR)/msr.flat \ $(TEST_DIR)/hypercall.flat $(TEST_DIR)/sieve.flat \ $(TEST_DIR)/kvmclock_test.flat $(TEST_DIR)/eventinj.flat \ - $(TEST_DIR)/s3.flat + $(TEST_DIR)/s3.flat $(TEST_DIR)/pmu.flat tests-common += api/api-sample tests-common += api/dirty-log @@ -85,6 +85,8 @@ $(TEST_DIR)/eventinj.elf: $(cstart.o) $(TEST_DIR)/eventinj.o $(TEST_DIR)/s3.elf: $(cstart.o) $(TEST_DIR)/s3.o +$(TEST_DIR)/pmu.elf: $(cstart.o) $(TEST_DIR)/pmu.o + arch_clean: $(RM) $(TEST_DIR)/*.o $(TEST_DIR)/*.flat $(TEST_DIR)/*.elf \ $(TEST_DIR)/.*.d $(TEST_DIR)/lib/.*.d $(TEST_DIR)/lib/*.o diff --git a/x86/pmu.c b/x86/pmu.c new file mode 100644 index 0000000..1513ea7 --- /dev/null +++ b/x86/pmu.c @@ -0,0 +1,63 @@ + +#include "x86/msr.h" +#include "x86/processor.h" +#include "libcflat.h" +#include <stdint.h> + +#define N 1000000 + +static int tests, failures; + +static void loop() +{ + unsigned long tmp; + + asm volatile("1: nop; nop; nop; nop; nop; nop; nop; nop; nop; loop 1b" + : "=c"(tmp) : "0"(N)); + +} + +static uint64_t measure(uint32_t sel_unit) +{ + wrmsr(MSR_IA32_PERFCTR0, 0); + wrmsr(MSR_P6_EVNTSEL0, 0x430000 | sel_unit); // enable + loop(); + wrmsr(MSR_P6_EVNTSEL0, sel_unit); // disable + return rdmsr(MSR_IA32_PERFCTR0); +} + +static void report(const char *name, bool pass) +{ + printf("%s: pmu %s\n", pass ? "PASS" : "FAIL", name); + tests += 1; + failures += !pass; +} + +static void check(const char *name, uint32_t sel_unit, + float min, float max) +{ + bool pass; + uint64_t n; + + n = measure(sel_unit); + pass = n >= min * N && n <= max * N; + report(name, pass); +} + +static void check_rdpmc(void) +{ + uint64_t val = 0x123456789ull; + wrmsr(MSR_IA32_PERFCTR0, val); + report("rdpmc", rdpmc(0) == (u32)val); +} + +int main(int ac, char **av) +{ + check("cycles", 0x003c, 1, 15); + check("branches", 0x00c4, 1, 1.1); + check("branch misses", 0x00c5, 0, 0.1); + check("instructions", 0x00c0, 10, 10.2); + check_rdpmc(); + printf("\n%d tests, %d failures\n", tests, failures); + return !failures ? 0 : 1; +} -- 1.7.5.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html