All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jim Mattson <jmattson@google.com>
To: kvm@vger.kernel.org, pbonzini@redhat.com
Cc: Jim Mattson <jmattson@google.com>, Eric Hankland <ehankland@google.com>
Subject: [kvm-unit-tests PATCH] x86/pmu: Test PMU virtualization on emulated instructions
Date: Fri, 12 Nov 2021 15:56:52 -0800	[thread overview]
Message-ID: <20211112235652.1127814-1-jmattson@google.com> (raw)

Add tests of "instructions retired" and "branch instructions retired,"
to ensure that these events count emulated instructions.

Signed-off-by: Eric Hankland <ehankland@google.com>
[jmattson:
  - Added command-line parameter to conditionally run the new tests.
  - Added pmu-emulation test to unittests.cfg
]
Signed-off-by: Jim Mattson <jmattson@google.com>
---
 x86/pmu.c         | 80 +++++++++++++++++++++++++++++++++++++++++++++++
 x86/unittests.cfg |  7 +++++
 2 files changed, 87 insertions(+)

diff --git a/x86/pmu.c b/x86/pmu.c
index ec61ac956a55..a159333b0c73 100644
--- a/x86/pmu.c
+++ b/x86/pmu.c
@@ -33,6 +33,12 @@
 
 #define N 1000000
 
+#define KVM_FEP "ud2; .byte 'k', 'v', 'm';"
+// These values match the number of instructions and branches in the
+// assembly block in check_emulated_instr().
+#define EXPECTED_INSTR 17
+#define EXPECTED_BRNCH 5
+
 typedef struct {
 	uint32_t ctr;
 	uint32_t config;
@@ -468,6 +474,77 @@ static void check_running_counter_wrmsr(void)
 	report_prefix_pop();
 }
 
+static void check_emulated_instr(void)
+{
+	uint64_t status, instr_start, brnch_start;
+	pmu_counter_t brnch_cnt = {
+		.ctr = MSR_IA32_PERFCTR0,
+		/* branch instructions */
+		.config = EVNTSEL_OS | EVNTSEL_USR | gp_events[5].unit_sel,
+		.count = 0,
+	};
+	pmu_counter_t instr_cnt = {
+		.ctr = MSR_IA32_PERFCTR0 + 1,
+		/* instructions */
+		.config = EVNTSEL_OS | EVNTSEL_USR | gp_events[1].unit_sel,
+		.count = 0,
+	};
+	report_prefix_push("emulated instruction");
+
+	wrmsr(MSR_CORE_PERF_GLOBAL_OVF_CTRL,
+	      rdmsr(MSR_CORE_PERF_GLOBAL_STATUS));
+
+	start_event(&brnch_cnt);
+	start_event(&instr_cnt);
+
+	brnch_start = -EXPECTED_BRNCH;
+	instr_start = -EXPECTED_INSTR;
+	wrmsr(MSR_IA32_PERFCTR0, brnch_start);
+	wrmsr(MSR_IA32_PERFCTR0 + 1, instr_start);
+	// KVM_FEP is a magic prefix that forces emulation so
+	// 'KVM_FEP "jne label\n"' just counts as a single instruction.
+	asm volatile(
+		"mov $0x0, %%eax\n"
+		"cmp $0x0, %%eax\n"
+		KVM_FEP "jne label\n"
+		KVM_FEP "jne label\n"
+		KVM_FEP "jne label\n"
+		KVM_FEP "jne label\n"
+		KVM_FEP "jne label\n"
+		"mov $0xa, %%eax\n"
+		"cpuid\n"
+		"mov $0xa, %%eax\n"
+		"cpuid\n"
+		"mov $0xa, %%eax\n"
+		"cpuid\n"
+		"mov $0xa, %%eax\n"
+		"cpuid\n"
+		"mov $0xa, %%eax\n"
+		"cpuid\n"
+		"label:\n"
+		:
+		:
+		: "eax", "ebx", "ecx", "edx");
+
+	wrmsr(MSR_CORE_PERF_GLOBAL_CTRL, 0);
+
+	stop_event(&brnch_cnt);
+	stop_event(&instr_cnt);
+
+	// Check that the end count - start count is at least the expected
+	// number of instructions and branches.
+	report(instr_cnt.count - instr_start >= EXPECTED_INSTR,
+	       "instruction count");
+	report(brnch_cnt.count - brnch_start >= EXPECTED_BRNCH,
+	       "branch count");
+	// Additionally check that those counters overflowed properly.
+	status = rdmsr(MSR_CORE_PERF_GLOBAL_STATUS);
+	report(status & 1, "instruction counter overflow");
+	report(status & 2, "branch counter overflow");
+
+	report_prefix_pop();
+}
+
 static void check_counters(void)
 {
 	check_gp_counters();
@@ -563,6 +640,9 @@ int main(int ac, char **av)
 
 	check_counters();
 
+	if (ac > 1 && !strcmp(av[1], "emulation"))
+		check_emulated_instr();
+
 	if (rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES) {
 		gp_counter_base = MSR_IA32_PMC0;
 		report_prefix_push("full-width writes");
diff --git a/x86/unittests.cfg b/x86/unittests.cfg
index 3000e53c790f..2aedb24dc4ff 100644
--- a/x86/unittests.cfg
+++ b/x86/unittests.cfg
@@ -185,6 +185,13 @@ extra_params = -cpu host,migratable=no
 check = /sys/module/kvm/parameters/ignore_msrs=N
 check = /proc/sys/kernel/nmi_watchdog=0
 
+[pmu_emulation]
+file = pmu.flat
+arch = x86_64
+extra_params = -cpu max -append emulation
+check = /sys/module/kvm_intel/parameters/force_emulation_prefix=Y
+check = /proc/sys/kernel/nmi_watchdog=0
+
 [vmware_backdoors]
 file = vmware_backdoors.flat
 extra_params = -machine vmport=on -cpu max
-- 
2.34.0.rc1.387.gb447b232ab-goog


             reply	other threads:[~2021-11-12 23:56 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-12 23:56 Jim Mattson [this message]
2021-11-16 10:04 ` [kvm-unit-tests PATCH] x86/pmu: Test PMU virtualization on emulated instructions Like Xu
2021-11-16 10:45   ` Paolo Bonzini
2021-12-17  9:47 Ma Xinjian
2021-12-17 14:40 ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211112235652.1127814-1-jmattson@google.com \
    --to=jmattson@google.com \
    --cc=ehankland@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.