Commit 1b1d1b17 authored by Oliver Upton's avatar Oliver Upton
Browse files

Merge branch 'kvm-arm64/pmuv3-asahi' into kvmarm/next



* kvm-arm64/pmuv3-asahi:
  : Support PMUv3 for KVM guests on Apple silicon
  :
  : Take advantage of some IMPLEMENTATION DEFINED traps available on Apple
  : parts to trap-and-emulate the PMUv3 registers on behalf of a KVM guest.
  : Constrain the vPMU to a cycle counter and single event counter, as the
  : Apple PMU has events that cannot be counted on every counter.
  :
  : There is a small new interface between the ARM PMU driver and KVM, where
  : the PMU driver owns the PMUv3 -> hardware event mappings.
  arm64: Enable IMP DEF PMUv3 traps on Apple M*
  KVM: arm64: Provide 1 event counter on IMPDEF hardware
  drivers/perf: apple_m1: Provide helper for mapping PMUv3 events
  KVM: arm64: Remap PMUv3 events onto hardware
  KVM: arm64: Advertise PMUv3 if IMPDEF traps are present
  KVM: arm64: Compute synthetic sysreg ESR for Apple PMUv3 traps
  KVM: arm64: Move PMUVer filtering into KVM code
  KVM: arm64: Use guard() to cleanup usage of arm_pmus_lock
  KVM: arm64: Drop kvm_arm_pmu_available static key
  KVM: arm64: Use a cpucap to determine if system supports FEAT_PMUv3
  KVM: arm64: Always support SW_INCR PMU event
  KVM: arm64: Compute PMCEID from arm_pmu's event bitmaps
  drivers/perf: apple_m1: Support host/guest event filtering
  drivers/perf: apple_m1: Refactor event select/filter configuration

Signed-off-by: default avatarOliver Upton <oliver.upton@linux.dev>
parents d300b016 e1231aac
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#define PMCR0_PMI_ENABLE_8_9	GENMASK(45, 44)

#define SYS_IMP_APL_PMCR1_EL1	sys_reg(3, 1, 15, 1, 0)
#define SYS_IMP_APL_PMCR1_EL12	sys_reg(3, 1, 15, 7, 2)
#define PMCR1_COUNT_A64_EL0_0_7	GENMASK(15, 8)
#define PMCR1_COUNT_A64_EL1_0_7	GENMASK(23, 16)
#define PMCR1_COUNT_A64_EL0_8_9	GENMASK(41, 40)
+2 −0
Original line number Diff line number Diff line
@@ -71,6 +71,8 @@ cpucap_is_possible(const unsigned int cap)
		 * KVM MPAM support doesn't rely on the host kernel supporting MPAM.
		*/
		return true;
	case ARM64_HAS_PMUV3:
		return IS_ENABLED(CONFIG_HW_PERF_EVENTS);
	}

	return true;
+5 −23
Original line number Diff line number Diff line
@@ -525,29 +525,6 @@ cpuid_feature_extract_unsigned_field(u64 features, int field)
	return cpuid_feature_extract_unsigned_field_width(features, field, 4);
}

/*
 * Fields that identify the version of the Performance Monitors Extension do
 * not follow the standard ID scheme. See ARM DDI 0487E.a page D13-2825,
 * "Alternative ID scheme used for the Performance Monitors Extension version".
 */
static inline u64 __attribute_const__
cpuid_feature_cap_perfmon_field(u64 features, int field, u64 cap)
{
	u64 val = cpuid_feature_extract_unsigned_field(features, field);
	u64 mask = GENMASK_ULL(field + 3, field);

	/* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
	if (val == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
		val = 0;

	if (val > cap) {
		features &= ~mask;
		features |= (cap << field) & mask;
	}

	return features;
}

static inline u64 arm64_ftr_mask(const struct arm64_ftr_bits *ftrp)
{
	return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
@@ -866,6 +843,11 @@ static __always_inline bool system_supports_mpam_hcr(void)
	return alternative_has_cap_unlikely(ARM64_MPAM_HCR);
}

static inline bool system_supports_pmuv3(void)
{
	return cpus_have_final_cap(ARM64_HAS_PMUV3);
}

int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
bool try_emulate_mrs(struct pt_regs *regs, u32 isn);

+44 −0
Original line number Diff line number Diff line
@@ -247,6 +247,43 @@ has_neoverse_n1_erratum_1542419(const struct arm64_cpu_capabilities *entry,
	return is_midr_in_range(&range) && has_dic;
}

static const struct midr_range impdef_pmuv3_cpus[] = {
	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_PRO),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_PRO),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_MAX),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_MAX),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_PRO),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_PRO),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_MAX),
	MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_MAX),
	{},
};

static bool has_impdef_pmuv3(const struct arm64_cpu_capabilities *entry, int scope)
{
	u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
	unsigned int pmuver;

	if (!is_kernel_in_hyp_mode())
		return false;

	pmuver = cpuid_feature_extract_unsigned_field(dfr0,
						      ID_AA64DFR0_EL1_PMUVer_SHIFT);
	if (pmuver != ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
		return false;

	return is_midr_in_range_list(impdef_pmuv3_cpus);
}

static void cpu_enable_impdef_pmuv3_traps(const struct arm64_cpu_capabilities *__unused)
{
	sysreg_clear_set_s(SYS_HACR_EL2, 0, BIT(56));
}

#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
@@ -847,6 +884,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
					{}
				})),
	},
	{
		.desc = "Apple IMPDEF PMUv3 Traps",
		.capability = ARM64_WORKAROUND_PMUV3_IMPDEF_TRAPS,
		.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
		.matches = has_impdef_pmuv3,
		.cpu_enable = cpu_enable_impdef_pmuv3_traps,
	},
	{
	}
};
+30 −0
Original line number Diff line number Diff line
@@ -1900,6 +1900,28 @@ static bool has_lpa2(const struct arm64_cpu_capabilities *entry, int scope)
}
#endif

#ifdef CONFIG_HW_PERF_EVENTS
static bool has_pmuv3(const struct arm64_cpu_capabilities *entry, int scope)
{
	u64 dfr0 = read_sanitised_ftr_reg(SYS_ID_AA64DFR0_EL1);
	unsigned int pmuver;

	/*
	 * PMUVer follows the standard ID scheme for an unsigned field with the
	 * exception of 0xF (IMP_DEF) which is treated specially and implies
	 * FEAT_PMUv3 is not implemented.
	 *
	 * See DDI0487L.a D24.1.3.2 for more details.
	 */
	pmuver = cpuid_feature_extract_unsigned_field(dfr0,
						      ID_AA64DFR0_EL1_PMUVer_SHIFT);
	if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF)
		return false;

	return pmuver >= ID_AA64DFR0_EL1_PMUVer_IMP;
}
#endif

#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
#define KPTI_NG_TEMP_VA		(-(1UL << PMD_SHIFT))

@@ -3010,6 +3032,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
		.matches = has_cpuid_feature,
		ARM64_CPUID_FIELDS(ID_AA64PFR1_EL1, GCS, IMP)
	},
#endif
#ifdef CONFIG_HW_PERF_EVENTS
	{
		.desc = "PMUv3",
		.capability = ARM64_HAS_PMUV3,
		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
		.matches = has_pmuv3,
	},
#endif
	{},
};
Loading