Commit c41ef29c authored by Aaron Lewis's avatar Aaron Lewis Committed by Paolo Bonzini

selftests: kvm/x86: Verify the pmu event filter matches the correct event

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: default avatarAaron Lewis <aaronlewis@google.com>
Message-Id: <20220517051238.2566934-3-aaronlewis@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 04baa223
...@@ -281,6 +281,22 @@ static uint64_t test_with_filter(struct kvm_vm *vm, ...@@ -281,6 +281,22 @@ static uint64_t test_with_filter(struct kvm_vm *vm,
return run_vm_to_sync(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) static void test_member_deny_list(struct kvm_vm *vm)
{ {
struct kvm_pmu_event_filter *f = event_filter(KVM_PMU_EVENT_DENY); struct kvm_pmu_event_filter *f = event_filter(KVM_PMU_EVENT_DENY);
...@@ -463,6 +479,9 @@ int main(int argc, char *argv[]) ...@@ -463,6 +479,9 @@ int main(int argc, char *argv[])
exit(KSFT_SKIP); exit(KSFT_SKIP);
} }
if (use_amd_pmu())
test_amd_deny_list(vm);
test_without_filter(vm); test_without_filter(vm);
test_member_deny_list(vm); test_member_deny_list(vm);
test_member_allow_list(vm); test_member_allow_list(vm);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment