Commit 203f2b95 authored by Mark Brown's avatar Mark Brown Committed by Catalin Marinas
Browse files

arm64/fpsimd: Support FEAT_FPMR



FEAT_FPMR defines a new EL0 accessible register FPMR use to configure the
FP8 related features added to the architecture at the same time. Detect
support for this register and context switch it for EL0 when present.

Due to the sharing of responsibility for saving floating point state
between the host kernel and KVM FP8 support is not yet implemented in KVM
and a stub similar to that used for SVCR is provided for FPMR in order to
avoid bisection issues. To make it easier to share host state with the
hypervisor we store FPMR as a hardened usercopy field in uw (along with
some padding).

Signed-off-by: default avatarMark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20240306-arm64-2023-dpisa-v5-3-c568edc8ed7f@kernel.org


Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent b6c0b424
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -768,6 +768,11 @@ static __always_inline bool system_supports_tpidr2(void)
	return system_supports_sme();
}

static __always_inline bool system_supports_fpmr(void)
{
	return alternative_has_cap_unlikely(ARM64_HAS_FPMR);
}

static __always_inline bool system_supports_cnp(void)
{
	return alternative_has_cap_unlikely(ARM64_HAS_CNP);
+2 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@ struct cpu_fp_state {
	void *sve_state;
	void *sme_state;
	u64 *svcr;
	u64 *fpmr;
	unsigned int sve_vl;
	unsigned int sme_vl;
	enum fp_type *fp_type;
@@ -154,6 +155,7 @@ extern void cpu_enable_sve(const struct arm64_cpu_capabilities *__unused);
extern void cpu_enable_sme(const struct arm64_cpu_capabilities *__unused);
extern void cpu_enable_sme2(const struct arm64_cpu_capabilities *__unused);
extern void cpu_enable_fa64(const struct arm64_cpu_capabilities *__unused);
extern void cpu_enable_fpmr(const struct arm64_cpu_capabilities *__unused);

extern u64 read_smcr_features(void);

+1 −0
Original line number Diff line number Diff line
@@ -543,6 +543,7 @@ struct kvm_vcpu_arch {
	enum fp_type fp_type;
	unsigned int sve_max_vl;
	u64 svcr;
	u64 fpmr;

	/* Stage 2 paging state used by the hardware on next switch */
	struct kvm_s2_mmu *hw_mmu;
+4 −0
Original line number Diff line number Diff line
@@ -155,6 +155,8 @@ struct thread_struct {
	struct {
		unsigned long	tp_value;	/* TLS register */
		unsigned long	tp2_value;
		u64		fpmr;
		unsigned long	pad;
		struct user_fpsimd_state fpsimd_state;
	} uw;

@@ -253,6 +255,8 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
	BUILD_BUG_ON(sizeof_field(struct thread_struct, uw) !=
		     sizeof_field(struct thread_struct, uw.tp_value) +
		     sizeof_field(struct thread_struct, uw.tp2_value) +
		     sizeof_field(struct thread_struct, uw.fpmr) +
		     sizeof_field(struct thread_struct, uw.pad) +
		     sizeof_field(struct thread_struct, uw.fpsimd_state));

	*offset = offsetof(struct thread_struct, uw);
+9 −0
Original line number Diff line number Diff line
@@ -272,6 +272,7 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {
};

static const struct arm64_ftr_bits ftr_id_aa64pfr2[] = {
	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR2_EL1_FPMR_SHIFT, 4, 0),
	ARM64_FTR_END,
};

@@ -2767,6 +2768,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
		.matches = has_lpa2,
	},
	{
		.desc = "FPMR",
		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
		.capability = ARM64_HAS_FPMR,
		.matches = has_cpuid_feature,
		.cpu_enable = cpu_enable_fpmr,
		ARM64_CPUID_FIELDS(ID_AA64PFR2_EL1, FPMR, IMP)
	},
	{},
};

Loading