Skip to content

Commit 203f2b9

Browse files
brooniectmarinas
authored andcommitted
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: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent b6c0b42 commit 203f2b9

File tree

8 files changed

+36
-0
lines changed

8 files changed

+36
-0
lines changed

arch/arm64/include/asm/cpufeature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,11 @@ static __always_inline bool system_supports_tpidr2(void)
768768
return system_supports_sme();
769769
}
770770

771+
static __always_inline bool system_supports_fpmr(void)
772+
{
773+
return alternative_has_cap_unlikely(ARM64_HAS_FPMR);
774+
}
775+
771776
static __always_inline bool system_supports_cnp(void)
772777
{
773778
return alternative_has_cap_unlikely(ARM64_HAS_CNP);

arch/arm64/include/asm/fpsimd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ struct cpu_fp_state {
8989
void *sve_state;
9090
void *sme_state;
9191
u64 *svcr;
92+
u64 *fpmr;
9293
unsigned int sve_vl;
9394
unsigned int sme_vl;
9495
enum fp_type *fp_type;
@@ -154,6 +155,7 @@ extern void cpu_enable_sve(const struct arm64_cpu_capabilities *__unused);
154155
extern void cpu_enable_sme(const struct arm64_cpu_capabilities *__unused);
155156
extern void cpu_enable_sme2(const struct arm64_cpu_capabilities *__unused);
156157
extern void cpu_enable_fa64(const struct arm64_cpu_capabilities *__unused);
158+
extern void cpu_enable_fpmr(const struct arm64_cpu_capabilities *__unused);
157159

158160
extern u64 read_smcr_features(void);
159161

arch/arm64/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,7 @@ struct kvm_vcpu_arch {
543543
enum fp_type fp_type;
544544
unsigned int sve_max_vl;
545545
u64 svcr;
546+
u64 fpmr;
546547

547548
/* Stage 2 paging state used by the hardware on next switch */
548549
struct kvm_s2_mmu *hw_mmu;

arch/arm64/include/asm/processor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ struct thread_struct {
155155
struct {
156156
unsigned long tp_value; /* TLS register */
157157
unsigned long tp2_value;
158+
u64 fpmr;
159+
unsigned long pad;
158160
struct user_fpsimd_state fpsimd_state;
159161
} uw;
160162

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

258262
*offset = offsetof(struct thread_struct, uw);

arch/arm64/kernel/cpufeature.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr1[] = {
272272
};
273273

274274
static const struct arm64_ftr_bits ftr_id_aa64pfr2[] = {
275+
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR2_EL1_FPMR_SHIFT, 4, 0),
275276
ARM64_FTR_END,
276277
};
277278

@@ -2767,6 +2768,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
27672768
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
27682769
.matches = has_lpa2,
27692770
},
2771+
{
2772+
.desc = "FPMR",
2773+
.type = ARM64_CPUCAP_SYSTEM_FEATURE,
2774+
.capability = ARM64_HAS_FPMR,
2775+
.matches = has_cpuid_feature,
2776+
.cpu_enable = cpu_enable_fpmr,
2777+
ARM64_CPUID_FIELDS(ID_AA64PFR2_EL1, FPMR, IMP)
2778+
},
27702779
{},
27712780
};
27722781

arch/arm64/kernel/fpsimd.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,9 @@ static void task_fpsimd_load(void)
359359
WARN_ON(preemptible());
360360
WARN_ON(test_thread_flag(TIF_KERNEL_FPSTATE));
361361

362+
if (system_supports_fpmr())
363+
write_sysreg_s(current->thread.uw.fpmr, SYS_FPMR);
364+
362365
if (system_supports_sve() || system_supports_sme()) {
363366
switch (current->thread.fp_type) {
364367
case FP_STATE_FPSIMD:
@@ -446,6 +449,9 @@ static void fpsimd_save_user_state(void)
446449
if (test_thread_flag(TIF_FOREIGN_FPSTATE))
447450
return;
448451

452+
if (system_supports_fpmr())
453+
*(last->fpmr) = read_sysreg_s(SYS_FPMR);
454+
449455
/*
450456
* If a task is in a syscall the ABI allows us to only
451457
* preserve the state shared with FPSIMD so don't bother
@@ -688,6 +694,12 @@ static void sve_to_fpsimd(struct task_struct *task)
688694
}
689695
}
690696

697+
void cpu_enable_fpmr(const struct arm64_cpu_capabilities *__always_unused p)
698+
{
699+
write_sysreg_s(read_sysreg_s(SYS_SCTLR_EL1) | SCTLR_EL1_EnFPM_MASK,
700+
SYS_SCTLR_EL1);
701+
}
702+
691703
#ifdef CONFIG_ARM64_SVE
692704
/*
693705
* Call __sve_free() directly only if you know task can't be scheduled
@@ -1680,6 +1692,7 @@ static void fpsimd_bind_task_to_cpu(void)
16801692
last->sve_vl = task_get_sve_vl(current);
16811693
last->sme_vl = task_get_sme_vl(current);
16821694
last->svcr = &current->thread.svcr;
1695+
last->fpmr = &current->thread.uw.fpmr;
16831696
last->fp_type = &current->thread.fp_type;
16841697
last->to_save = FP_STATE_CURRENT;
16851698
current->thread.fpsimd_cpu = smp_processor_id();

arch/arm64/kvm/fpsimd.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
153153
fp_state.sve_vl = vcpu->arch.sve_max_vl;
154154
fp_state.sme_state = NULL;
155155
fp_state.svcr = &vcpu->arch.svcr;
156+
fp_state.fpmr = &vcpu->arch.fpmr;
156157
fp_state.fp_type = &vcpu->arch.fp_type;
157158

158159
if (vcpu_has_sve(vcpu))

arch/arm64/tools/cpucaps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ HAS_ECV
2626
HAS_ECV_CNTPOFF
2727
HAS_EPAN
2828
HAS_EVT
29+
HAS_FPMR
2930
HAS_FGT
3031
HAS_FPSIMD
3132
HAS_GENERIC_AUTH

0 commit comments

Comments
 (0)