tools/testing/selftests/kvm/arm64/vpmu_counter_access.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/arm64/vpmu_counter_access.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/arm64/vpmu_counter_access.c
Extension
.c
Size
19285 bytes
Lines
644
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct vpmu_vm {
	struct kvm_vm *vm;
	struct kvm_vcpu *vcpu;
};

static struct vpmu_vm vpmu_vm;

struct pmreg_sets {
	u64 set_reg_id;
	u64 clr_reg_id;
};

#define PMREG_SET(set, clr) {.set_reg_id = set, .clr_reg_id = clr}

static u64 get_pmcr_n(u64 pmcr)
{
	return FIELD_GET(ARMV8_PMU_PMCR_N, pmcr);
}

static u64 get_counters_mask(u64 n)
{
	u64 mask = BIT(ARMV8_PMU_CYCLE_IDX);

	if (n)
		mask |= GENMASK(n - 1, 0);
	return mask;
}

/* Read PMEVTCNTR<n>_EL0 through PMXEVCNTR_EL0 */
static inline unsigned long read_sel_evcntr(int sel)
{
	write_sysreg(sel, pmselr_el0);
	isb();
	return read_sysreg(pmxevcntr_el0);
}

/* Write PMEVTCNTR<n>_EL0 through PMXEVCNTR_EL0 */
static inline void write_sel_evcntr(int sel, unsigned long val)
{
	write_sysreg(sel, pmselr_el0);
	isb();
	write_sysreg(val, pmxevcntr_el0);
	isb();
}

/* Read PMEVTYPER<n>_EL0 through PMXEVTYPER_EL0 */
static inline unsigned long read_sel_evtyper(int sel)
{
	write_sysreg(sel, pmselr_el0);
	isb();
	return read_sysreg(pmxevtyper_el0);
}

/* Write PMEVTYPER<n>_EL0 through PMXEVTYPER_EL0 */
static inline void write_sel_evtyper(int sel, unsigned long val)
{
	write_sysreg(sel, pmselr_el0);
	isb();
	write_sysreg(val, pmxevtyper_el0);
	isb();
}

static void pmu_disable_reset(void)
{
	u64 pmcr = read_sysreg(pmcr_el0);

	/* Reset all counters, disabling them */
	pmcr &= ~ARMV8_PMU_PMCR_E;
	write_sysreg(pmcr | ARMV8_PMU_PMCR_P, pmcr_el0);
	isb();
}

#define RETURN_READ_PMEVCNTRN(n) \
	return read_sysreg(pmevcntr##n##_el0)
static unsigned long read_pmevcntrn(int n)
{
	PMEVN_SWITCH(n, RETURN_READ_PMEVCNTRN);
	return 0;
}

#define WRITE_PMEVCNTRN(n) \
	write_sysreg(val, pmevcntr##n##_el0)
static void write_pmevcntrn(int n, unsigned long val)
{
	PMEVN_SWITCH(n, WRITE_PMEVCNTRN);
	isb();
}

#define READ_PMEVTYPERN(n) \
	return read_sysreg(pmevtyper##n##_el0)

Annotation

Implementation Notes