arch/x86/kvm/pmu.h

Source file repositories/reference/linux-study-clean/arch/x86/kvm/pmu.h

File Facts

System
Linux kernel
Corpus path
arch/x86/kvm/pmu.h
Extension
.h
Size
9315 bytes
Lines
297
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct kvm_pmu_ops {
	struct kvm_pmc *(*rdpmc_ecx_to_pmc)(struct kvm_vcpu *vcpu,
		unsigned int idx, u64 *mask);
	struct kvm_pmc *(*msr_idx_to_pmc)(struct kvm_vcpu *vcpu, u32 msr);
	int (*check_rdpmc_early)(struct kvm_vcpu *vcpu, unsigned int idx);
	bool (*is_valid_msr)(struct kvm_vcpu *vcpu, u32 msr);
	int (*get_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
	int (*set_msr)(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
	void (*refresh)(struct kvm_vcpu *vcpu);
	void (*init)(struct kvm_vcpu *vcpu);
	void (*reset)(struct kvm_vcpu *vcpu);
	void (*deliver_pmi)(struct kvm_vcpu *vcpu);
	void (*cleanup)(struct kvm_vcpu *vcpu);
	bool (*pmc_is_disabled_in_current_mode)(struct kvm_pmc *pmc);

	bool (*is_mediated_pmu_supported)(struct x86_pmu_capability *host_pmu);
	void (*mediated_load)(struct kvm_vcpu *vcpu);
	void (*mediated_put)(struct kvm_vcpu *vcpu);
	void (*write_global_ctrl)(u64 global_ctrl);

	const u64 EVENTSEL_EVENT;
	const int MAX_NR_GP_COUNTERS;
	const int MIN_NR_GP_COUNTERS;

	const u32 PERF_GLOBAL_CTRL;
	const u32 GP_EVENTSEL_BASE;
	const u32 GP_COUNTER_BASE;
	const u32 FIXED_COUNTER_BASE;
	const u32 MSR_STRIDE;
};

#define kvm_pmu_call(func) static_call(kvm_x86_pmu_##func)

#define KVM_X86_PMU_OP(func) \
	DECLARE_STATIC_CALL(kvm_x86_pmu_##func, *(((struct kvm_pmu_ops *)0)->func));
#define KVM_X86_PMU_OP_OPTIONAL KVM_X86_PMU_OP
#define KVM_X86_PMU_OP_OPTIONAL_RET0 KVM_X86_PMU_OP
#include <asm/kvm-x86-pmu-ops.h>

extern bool enable_pmu;
extern bool enable_mediated_pmu;

void kvm_pmu_ops_update(const struct kvm_pmu_ops *pmu_ops);

void kvm_handle_guest_mediated_pmi(void);

static inline bool kvm_pmu_has_perf_global_ctrl(struct kvm_pmu *pmu)
{
	/*
	 * Architecturally, Intel's SDM states that IA32_PERF_GLOBAL_CTRL is
	 * supported if "CPUID.0AH: EAX[7:0] > 0", i.e. if the PMU version is
	 * greater than zero.  However, KVM only exposes and emulates the MSR
	 * to/for the guest if the guest PMU supports at least "Architectural
	 * Performance Monitoring Version 2".
	 *
	 * AMD's version of PERF_GLOBAL_CTRL conveniently shows up with v2.
	 */
	return pmu->version > 1;
}

static inline bool kvm_vcpu_has_mediated_pmu(struct kvm_vcpu *vcpu)
{
	return enable_mediated_pmu && vcpu_to_pmu(vcpu)->version;
}

/*
 * KVM tracks all counters in 64-bit bitmaps, with general purpose counters
 * mapped to bits 31:0 and fixed counters mapped to 63:32, e.g. fixed counter 0
 * is tracked internally via index 32.  On Intel, (AMD doesn't support fixed
 * counters), this mirrors how fixed counters are mapped to PERF_GLOBAL_CTRL
 * and similar MSRs, i.e. tracking fixed counters at base index 32 reduces the
 * amounter of boilerplate needed to iterate over PMCs *and* simplifies common
 * enabling/disable/reset operations.
 *
 * WARNING!  This helper is only for lookups that are initiated by KVM, it is
 * NOT safe for guest lookups, e.g. will do the wrong thing if passed a raw
 * ECX value from RDPMC (fixed counters are accessed by setting bit 30 in ECX
 * for RDPMC, not by adding 32 to the fixed counter index).
 */
static inline struct kvm_pmc *kvm_pmc_idx_to_pmc(struct kvm_pmu *pmu, int idx)
{
	if (idx < pmu->nr_arch_gp_counters)
		return &pmu->gp_counters[idx];

	idx -= KVM_FIXED_PMC_BASE_IDX;
	if (idx >= 0 && idx < pmu->nr_arch_fixed_counters)
		return &pmu->fixed_counters[idx];

	return NULL;
}

Annotation

Implementation Notes