cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vmx_pmu_caps_test.c (3433B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Test for VMX-pmu perf capability msr
      4 *
      5 * Copyright (C) 2021 Intel Corporation
      6 *
      7 * Test to check the effect of various CPUID settings on
      8 * MSR_IA32_PERF_CAPABILITIES MSR, and check that what
      9 * we write with KVM_SET_MSR is _not_ modified by the guest
     10 * and check it can be retrieved with KVM_GET_MSR, also test
     11 * the invalid LBR formats are rejected.
     12 */
     13
     14#define _GNU_SOURCE /* for program_invocation_short_name */
     15#include <sys/ioctl.h>
     16
     17#include "kvm_util.h"
     18#include "vmx.h"
     19
     20#define VCPU_ID	      0
     21
     22#define X86_FEATURE_PDCM	(1<<15)
     23#define PMU_CAP_FW_WRITES	(1ULL << 13)
     24#define PMU_CAP_LBR_FMT		0x3f
     25
     26union cpuid10_eax {
     27	struct {
     28		unsigned int version_id:8;
     29		unsigned int num_counters:8;
     30		unsigned int bit_width:8;
     31		unsigned int mask_length:8;
     32	} split;
     33	unsigned int full;
     34};
     35
     36union perf_capabilities {
     37	struct {
     38		u64	lbr_format:6;
     39		u64	pebs_trap:1;
     40		u64	pebs_arch_reg:1;
     41		u64	pebs_format:4;
     42		u64	smm_freeze:1;
     43		u64	full_width_write:1;
     44		u64 pebs_baseline:1;
     45		u64	perf_metrics:1;
     46		u64	pebs_output_pt_available:1;
     47		u64	anythread_deprecated:1;
     48	};
     49	u64	capabilities;
     50};
     51
     52static void guest_code(void)
     53{
     54	wrmsr(MSR_IA32_PERF_CAPABILITIES, PMU_CAP_LBR_FMT);
     55}
     56
     57int main(int argc, char *argv[])
     58{
     59	struct kvm_cpuid2 *cpuid;
     60	struct kvm_cpuid_entry2 *entry_1_0;
     61	struct kvm_cpuid_entry2 *entry_a_0;
     62	bool pdcm_supported = false;
     63	struct kvm_vm *vm;
     64	int ret;
     65	union cpuid10_eax eax;
     66	union perf_capabilities host_cap;
     67
     68	host_cap.capabilities = kvm_get_feature_msr(MSR_IA32_PERF_CAPABILITIES);
     69	host_cap.capabilities &= (PMU_CAP_FW_WRITES | PMU_CAP_LBR_FMT);
     70
     71	/* Create VM */
     72	vm = vm_create_default(VCPU_ID, 0, guest_code);
     73	cpuid = kvm_get_supported_cpuid();
     74
     75	if (kvm_get_cpuid_max_basic() >= 0xa) {
     76		entry_1_0 = kvm_get_supported_cpuid_index(1, 0);
     77		entry_a_0 = kvm_get_supported_cpuid_index(0xa, 0);
     78		pdcm_supported = entry_1_0 && !!(entry_1_0->ecx & X86_FEATURE_PDCM);
     79		eax.full = entry_a_0->eax;
     80	}
     81	if (!pdcm_supported) {
     82		print_skip("MSR_IA32_PERF_CAPABILITIES is not supported by the vCPU");
     83		exit(KSFT_SKIP);
     84	}
     85	if (!eax.split.version_id) {
     86		print_skip("PMU is not supported by the vCPU");
     87		exit(KSFT_SKIP);
     88	}
     89
     90	/* testcase 1, set capabilities when we have PDCM bit */
     91	vcpu_set_cpuid(vm, VCPU_ID, cpuid);
     92	vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, PMU_CAP_FW_WRITES);
     93
     94	/* check capabilities can be retrieved with KVM_GET_MSR */
     95	ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), PMU_CAP_FW_WRITES);
     96
     97	/* check whatever we write with KVM_SET_MSR is _not_ modified */
     98	vcpu_run(vm, VCPU_ID);
     99	ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), PMU_CAP_FW_WRITES);
    100
    101	/* testcase 2, check valid LBR formats are accepted */
    102	vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, 0);
    103	ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), 0);
    104
    105	vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, host_cap.lbr_format);
    106	ASSERT_EQ(vcpu_get_msr(vm, VCPU_ID, MSR_IA32_PERF_CAPABILITIES), (u64)host_cap.lbr_format);
    107
    108	/* testcase 3, check invalid LBR format is rejected */
    109	/* Note, on Arch LBR capable platforms, LBR_FMT in perf capability msr is 0x3f,
    110	 * to avoid the failure, use a true invalid format 0x30 for the test. */
    111	ret = _vcpu_set_msr(vm, 0, MSR_IA32_PERF_CAPABILITIES, 0x30);
    112	TEST_ASSERT(ret == 0, "Bad PERF_CAPABILITIES didn't fail.");
    113
    114	printf("Completed perf capability tests.\n");
    115	kvm_vm_free(vm);
    116}