diff options
Diffstat (limited to 'arch/arm64/kernel/fpsimd.c')
| -rw-r--r-- | arch/arm64/kernel/fpsimd.c | 34 | 
1 files changed, 34 insertions, 0 deletions
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 25ceaee6b025..ebb0158997ca 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c @@ -359,6 +359,9 @@ static void task_fpsimd_load(void)  	WARN_ON(preemptible());  	WARN_ON(test_thread_flag(TIF_KERNEL_FPSTATE)); +	if (system_supports_fpmr()) +		write_sysreg_s(current->thread.uw.fpmr, SYS_FPMR); +  	if (system_supports_sve() || system_supports_sme()) {  		switch (current->thread.fp_type) {  		case FP_STATE_FPSIMD: @@ -446,6 +449,9 @@ static void fpsimd_save_user_state(void)  	if (test_thread_flag(TIF_FOREIGN_FPSTATE))  		return; +	if (system_supports_fpmr()) +		*(last->fpmr) = read_sysreg_s(SYS_FPMR); +  	/*  	 * If a task is in a syscall the ABI allows us to only  	 * preserve the state shared with FPSIMD so don't bother @@ -688,6 +694,12 @@ static void sve_to_fpsimd(struct task_struct *task)  	}  } +void cpu_enable_fpmr(const struct arm64_cpu_capabilities *__always_unused p) +{ +	write_sysreg_s(read_sysreg_s(SYS_SCTLR_EL1) | SCTLR_EL1_EnFPM_MASK, +		       SYS_SCTLR_EL1); +} +  #ifdef CONFIG_ARM64_SVE  /*   * Call __sve_free() directly only if you know task can't be scheduled @@ -1134,6 +1146,8 @@ void cpu_enable_sve(const struct arm64_cpu_capabilities *__always_unused p)  {  	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_ZEN_EL1EN, CPACR_EL1);  	isb(); + +	write_sysreg_s(0, SYS_ZCR_EL1);  }  void __init sve_setup(void) @@ -1245,6 +1259,9 @@ void cpu_enable_sme(const struct arm64_cpu_capabilities *__always_unused p)  	write_sysreg(read_sysreg(CPACR_EL1) | CPACR_EL1_SMEN_EL1EN, CPACR_EL1);  	isb(); +	/* Ensure all bits in SMCR are set to known values */ +	write_sysreg_s(0, SYS_SMCR_EL1); +  	/* Allow EL0 to access TPIDR2 */  	write_sysreg(read_sysreg(SCTLR_EL1) | SCTLR_ELx_ENTP2, SCTLR_EL1);  	isb(); @@ -1311,6 +1328,22 @@ void __init sme_setup(void)  		get_sme_default_vl());  } +void sme_suspend_exit(void) +{ +	u64 smcr = 0; + +	if (!system_supports_sme()) +		return; + +	if (system_supports_fa64()) +		smcr |= SMCR_ELx_FA64; +	if (system_supports_sme2()) +		smcr |= SMCR_ELx_EZT0; + +	write_sysreg_s(smcr, SYS_SMCR_EL1); +	write_sysreg_s(0, SYS_SMPRI_EL1); +} +  #endif /* CONFIG_ARM64_SME */  static void sve_init_regs(void) @@ -1680,6 +1713,7 @@ static void fpsimd_bind_task_to_cpu(void)  	last->sve_vl = task_get_sve_vl(current);  	last->sme_vl = task_get_sme_vl(current);  	last->svcr = ¤t->thread.svcr; +	last->fpmr = ¤t->thread.uw.fpmr;  	last->fp_type = ¤t->thread.fp_type;  	last->to_save = FP_STATE_CURRENT;  	current->thread.fpsimd_cpu = smp_processor_id();  |