Test that masked events are not using invalid bits, and if they are, ensure the pmu event filter is not accepted by KVM_SET_PMU_EVENT_FILTER. The only valid bits that can be used for masked events are set when using KVM_PMU_EVENT_ENCODE_MASKED_EVENT() with one caveat. If any bits in the high nybble[1] of the eventsel for AMD are used on Intel setting the pmu event filter with KVM_SET_PMU_EVENT_FILTER will fail. Also, because no validation was being done on the event list prior to the introduction of masked events, verify that this continues for the original event type (flags == 0). If invalid bits are set (bits other than eventsel+umask) the pmu event filter will be accepted by KVM_SET_PMU_EVENT_FILTER. [1] bits 35:32 in the event and bits 11:8 in the eventsel. Signed-off-by: Aaron Lewis <aaronlewis@xxxxxxxxxx> --- .../kvm/x86_64/pmu_event_filter_test.c | 31 +++++++++++++++++++ 1 file changed, 31 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 95beec32d9eb..344fee080c5e 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 @@ -610,6 +610,36 @@ static void test_inverted_masked_events(struct kvm_vm *vm) expect_failure(count); } +static void test_filter_ioctl(struct kvm_vm *vm) +{ + struct kvm_pmu_event_filter *f; + uint64_t e = ~0ul; + int r; + + /* + * Unfortunately having invalid bits set in event data is expected to + * pass when flags == 0 (bits other than eventsel+umask). + */ + f = create_pmu_event_filter(&e, 1, KVM_PMU_EVENT_ALLOW, 0); + r = _vm_ioctl(vm, KVM_SET_PMU_EVENT_FILTER, (void *)f); + TEST_ASSERT(r == 0, "Valid PMU Event Filter is failing"); + free(f); + + f = create_pmu_event_filter(&e, 1, KVM_PMU_EVENT_ALLOW, + KVM_PMU_EVENT_FLAG_MASKED_EVENTS); + r = _vm_ioctl(vm, KVM_SET_PMU_EVENT_FILTER, (void *)f); + TEST_ASSERT(r != 0, "Invalid PMU Event Filter is expected to fail"); + free(f); + + e = ENCODE_MASKED_EVENT(0xff, 0xff, 0xff, 0xf); + + f = create_pmu_event_filter(&e, 1, KVM_PMU_EVENT_ALLOW, + KVM_PMU_EVENT_FLAG_MASKED_EVENTS); + r = _vm_ioctl(vm, KVM_SET_PMU_EVENT_FILTER, (void *)f); + TEST_ASSERT(r == 0, "Valid PMU Event Filter is failing"); + free(f); +} + int main(int argc, char *argv[]) { void (*guest_code)(void) = NULL; @@ -656,6 +686,7 @@ int main(int argc, char *argv[]) test_masked_events(vm); test_inverted_masked_events(vm); + test_filter_ioctl(vm); kvm_vm_free(vm); -- 2.37.0.144.g8ac04bfd2-goog