All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] kvm: x86/pmu: Fix the compare function used by the pmu event filter
@ 2022-05-17  5:12 Aaron Lewis
  2022-05-17  5:12 ` [PATCH 2/3] selftests: kvm/x86: Add the helper function create_pmu_event_filter Aaron Lewis
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Aaron Lewis @ 2022-05-17  5:12 UTC (permalink / raw)
  To: kvm; +Cc: pbonzini, jmattson, seanjc, Aaron Lewis

When returning from the compare function the u64 is truncated to an
int.  This results in a loss of the high nybble[1] in the event select
and its sign if that nybble is in use.  Switch from using a result that
can end up being truncated to a result that can only be: 1, 0, -1.

[1] bits 35:32 in the event select register and bits 11:8 in the event
    select.

Fixes: 7ff775aca48ad ("KVM: x86/pmu: Use binary search to check filtered events")
Signed-off-by: Aaron Lewis <aaronlewis@google.com>
---
 arch/x86/kvm/pmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index eca39f56c231..1666e9d3e545 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -173,7 +173,7 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
 
 static int cmp_u64(const void *a, const void *b)
 {
-	return *(__u64 *)a - *(__u64 *)b;
+	return (*(u64 *)a > *(u64 *)b) - (*(u64 *)a < *(u64 *)b);
 }
 
 void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
-- 
2.36.1.124.g0e6072fb45-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] selftests: kvm/x86: Add the helper function create_pmu_event_filter
  2022-05-17  5:12 [PATCH 1/3] kvm: x86/pmu: Fix the compare function used by the pmu event filter Aaron Lewis
@ 2022-05-17  5:12 ` Aaron Lewis
  2022-05-17  5:12 ` [PATCH 3/3] selftests: kvm/x86: Verify the pmu event filter matches the correct event Aaron Lewis
  2022-05-18  0:57 ` [PATCH 1/3] kvm: x86/pmu: Fix the compare function used by the pmu event filter Sean Christopherson
  2 siblings, 0 replies; 4+ messages in thread
From: Aaron Lewis @ 2022-05-17  5:12 UTC (permalink / raw)
  To: kvm; +Cc: pbonzini, jmattson, seanjc, Aaron Lewis

Add a helper function that creates a pmu event filter given an event
list.  Currently, a pmu event filter can only be created with the same
hard coded event list.  Add a way to create one given a different event
list.

Also, rename make_pmu_event_filter to alloc_pmu_event_filter to clarify
it's purpose given the introduction of create_pmu_event_filter.

No functional changes intended.

Signed-off-by: Aaron Lewis <aaronlewis@google.com>
---
 .../kvm/x86_64/pmu_event_filter_test.c         | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c b/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
index 0d06ffa95d9d..30c1a5804210 100644
--- a/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
+++ b/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
@@ -208,7 +208,7 @@ static bool sanity_check_pmu(struct kvm_vm *vm)
 	return success;
 }
 
-static struct kvm_pmu_event_filter *make_pmu_event_filter(uint32_t nevents)
+static struct kvm_pmu_event_filter *alloc_pmu_event_filter(uint32_t nevents)
 {
 	struct kvm_pmu_event_filter *f;
 	int size = sizeof(*f) + nevents * sizeof(f->events[0]);
@@ -220,19 +220,29 @@ static struct kvm_pmu_event_filter *make_pmu_event_filter(uint32_t nevents)
 	return f;
 }
 
-static struct kvm_pmu_event_filter *event_filter(uint32_t action)
+
+static struct kvm_pmu_event_filter *
+create_pmu_event_filter(const uint64_t event_list[],
+			int nevents, uint32_t action)
 {
 	struct kvm_pmu_event_filter *f;
 	int i;
 
-	f = make_pmu_event_filter(ARRAY_SIZE(event_list));
+	f = alloc_pmu_event_filter(nevents);
 	f->action = action;
-	for (i = 0; i < ARRAY_SIZE(event_list); i++)
+	for (i = 0; i < nevents; i++)
 		f->events[i] = event_list[i];
 
 	return f;
 }
 
+static struct kvm_pmu_event_filter *event_filter(uint32_t action)
+{
+	return create_pmu_event_filter(event_list,
+				       ARRAY_SIZE(event_list),
+				       action);
+}
+
 /*
  * Remove the first occurrence of 'event' (if any) from the filter's
  * event list.
-- 
2.36.1.124.g0e6072fb45-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] selftests: kvm/x86: Verify the pmu event filter matches the correct event
  2022-05-17  5:12 [PATCH 1/3] kvm: x86/pmu: Fix the compare function used by the pmu event filter Aaron Lewis
  2022-05-17  5:12 ` [PATCH 2/3] selftests: kvm/x86: Add the helper function create_pmu_event_filter Aaron Lewis
@ 2022-05-17  5:12 ` Aaron Lewis
  2022-05-18  0:57 ` [PATCH 1/3] kvm: x86/pmu: Fix the compare function used by the pmu event filter Sean Christopherson
  2 siblings, 0 replies; 4+ messages in thread
From: Aaron Lewis @ 2022-05-17  5:12 UTC (permalink / raw)
  To: kvm; +Cc: pbonzini, jmattson, seanjc, Aaron Lewis

Add a test to demonstrate that when the guest programs an event select
it is matched correctly in the pmu event filter and not inadvertently
filtered.  This could happen on AMD if the high nybble[1] in the event
select gets truncated away only leaving the bottom byte[2] left for
matching.

This is a contrived example used for the convenience of demonstrating
this issue, however, this can be applied to event selects 0x28A (OC
Mode Switch) and 0x08A (L1 BTB Correction), where 0x08A could end up
being denied when the event select was only set up to deny 0x28A.

[1] bits 35:32 in the event select register and bits 11:8 in the event
    select.
[2] bits 7:0 in the event select register and bits 7:0 in the event
    select.

Signed-off-by: Aaron Lewis <aaronlewis@google.com>
---
 .../kvm/x86_64/pmu_event_filter_test.c        | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c b/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
index 30c1a5804210..93d77574b255 100644
--- a/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
+++ b/tools/testing/selftests/kvm/x86_64/pmu_event_filter_test.c
@@ -281,6 +281,22 @@ static uint64_t test_with_filter(struct kvm_vm *vm,
 	return run_vm_to_sync(vm);
 }
 
+static void test_amd_deny_list(struct kvm_vm *vm)
+{
+	uint64_t event = EVENT(0x1C2, 0);
+	struct kvm_pmu_event_filter *f;
+	uint64_t count;
+
+	f = create_pmu_event_filter(&event, 1, KVM_PMU_EVENT_DENY);
+	count = test_with_filter(vm, f);
+
+	free(f);
+	if (count != NUM_BRANCHES)
+		pr_info("%s: Branch instructions retired = %lu (expected %u)\n",
+			__func__, count, NUM_BRANCHES);
+	TEST_ASSERT(count, "Allowed PMU event is not counting");
+}
+
 static void test_member_deny_list(struct kvm_vm *vm)
 {
 	struct kvm_pmu_event_filter *f = event_filter(KVM_PMU_EVENT_DENY);
@@ -463,6 +479,9 @@ int main(int argc, char *argv[])
 		exit(KSFT_SKIP);
 	}
 
+	if (use_amd_pmu())
+		test_amd_deny_list(vm);
+
 	test_without_filter(vm);
 	test_member_deny_list(vm);
 	test_member_allow_list(vm);
-- 
2.36.1.124.g0e6072fb45-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/3] kvm: x86/pmu: Fix the compare function used by the pmu event filter
  2022-05-17  5:12 [PATCH 1/3] kvm: x86/pmu: Fix the compare function used by the pmu event filter Aaron Lewis
  2022-05-17  5:12 ` [PATCH 2/3] selftests: kvm/x86: Add the helper function create_pmu_event_filter Aaron Lewis
  2022-05-17  5:12 ` [PATCH 3/3] selftests: kvm/x86: Verify the pmu event filter matches the correct event Aaron Lewis
@ 2022-05-18  0:57 ` Sean Christopherson
  2 siblings, 0 replies; 4+ messages in thread
From: Sean Christopherson @ 2022-05-18  0:57 UTC (permalink / raw)
  To: Aaron Lewis; +Cc: kvm, pbonzini, jmattson

On Tue, May 17, 2022, Aaron Lewis wrote:
> When returning from the compare function the u64 is truncated to an
> int.  This results in a loss of the high nybble[1] in the event select
> and its sign if that nybble is in use.  Switch from using a result that
> can end up being truncated to a result that can only be: 1, 0, -1.
> 
> [1] bits 35:32 in the event select register and bits 11:8 in the event
>     select.
> 
> Fixes: 7ff775aca48ad ("KVM: x86/pmu: Use binary search to check filtered events")
> Signed-off-by: Aaron Lewis <aaronlewis@google.com>
> ---
>  arch/x86/kvm/pmu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> index eca39f56c231..1666e9d3e545 100644
> --- a/arch/x86/kvm/pmu.c
> +++ b/arch/x86/kvm/pmu.c
> @@ -173,7 +173,7 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
>  
>  static int cmp_u64(const void *a, const void *b)
>  {
> -	return *(__u64 *)a - *(__u64 *)b;
> +	return (*(u64 *)a > *(u64 *)b) - (*(u64 *)a < *(u64 *)b);

On one hand, this is downright evil.  On the other, it does generate branch-free
code, whereas gcc does not for explicit returns...

It's a little easier to read if the values are captured in local variables?

	u64 l = *(u64 *)a;
	u64 r = *(u64 *)b;

	return (l > r) - (l < r);

Either way,

Reviewed-by: Sean Christopherson <seanjc@google.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-05-18  0:57 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-17  5:12 [PATCH 1/3] kvm: x86/pmu: Fix the compare function used by the pmu event filter Aaron Lewis
2022-05-17  5:12 ` [PATCH 2/3] selftests: kvm/x86: Add the helper function create_pmu_event_filter Aaron Lewis
2022-05-17  5:12 ` [PATCH 3/3] selftests: kvm/x86: Verify the pmu event filter matches the correct event Aaron Lewis
2022-05-18  0:57 ` [PATCH 1/3] kvm: x86/pmu: Fix the compare function used by the pmu event filter Sean Christopherson

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.