summaryrefslogtreecommitdiff
path: root/arch/arm64/kernel
diff options
context:
space:
mode:
authorSe Wang (Patrick) Oh <sewango@codeaurora.org>2015-10-17 00:57:45 -0700
committerZhiqiang Tu <ztu@codeaurora.org>2017-03-24 11:05:22 +0800
commite92e3ed647b1609045d0ecb66987da04f75e980b (patch)
treec06369764a680cba021c3b17c5e153af5fef6a55 /arch/arm64/kernel
parentd4b4dcba33e7dcc38b6080d75f799568212b9222 (diff)
arm64: fpsimd: Enable FP(floating-point) settings for msm8996
Enable FP and SIMD settings for the MSM8996 during the execution of the AArch32 processes and disable these settings when you switch to the AArch64 processes. This commit also adds CONFIG_ENABLE_FP_SIMD_SETTINGS to support FP and SIMD settings. CRs-Fixed: 952837 Change-Id: If9537ca7390d8f08a6b48fb8865d1b349a93bcee Signed-off-by: Se Wang (Patrick) Oh <sewango@codeaurora.org> [ztu@codeaurora.org: Resolved conflicts] Signed-off-by: Zhiqiang Tu <ztu@codeaurora.org>
Diffstat (limited to 'arch/arm64/kernel')
-rw-r--r--arch/arm64/kernel/entry-fpsimd.S32
-rw-r--r--arch/arm64/kernel/entry.S13
-rw-r--r--arch/arm64/kernel/fpsimd.c23
3 files changed, 65 insertions, 3 deletions
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S
index c44a82f146b1..d90efa4852b2 100644
--- a/arch/arm64/kernel/entry-fpsimd.S
+++ b/arch/arm64/kernel/entry-fpsimd.S
@@ -64,4 +64,36 @@ ENTRY(fpsimd_load_partial_state)
ret
ENDPROC(fpsimd_load_partial_state)
+#ifdef CONFIG_ENABLE_FP_SIMD_SETTINGS
+ENTRY(fpsimd_enable_trap)
+ mrs x0, cpacr_el1
+ bic x0, x0, #(3 << 20)
+ orr x0, x0, #(1 << 20)
+ msr cpacr_el1, x0
+ ret
+ENDPROC(fpsimd_enable_trap)
+ENTRY(fpsimd_disable_trap)
+ mrs x0, cpacr_el1
+ orr x0, x0, #(3 << 20)
+ msr cpacr_el1, x0
+ ret
+ENDPROC(fpsimd_disable_trap)
+ENTRY(fpsimd_settings_enable)
+ mrs x0, s3_1_c15_c15_0
+ orr x0, x0, #(1 << 31)
+ isb
+ msr s3_1_c15_c15_0, x0
+ isb
+ ret
+ENDPROC(fpsimd_settings_enable)
+ENTRY(fpsimd_settings_disable)
+ mrs x0, s3_1_c15_c15_0
+ bic x0, x0, #(1 << 31)
+ isb
+ msr s3_1_c15_c15_0, x0
+ isb
+ ret
+ENDPROC(fpsimd_settings_disable)
+#endif
+
#endif
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index d311c635a00e..9e697d85149a 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -494,7 +494,7 @@ el0_sync_compat:
cmp x24, #ESR_ELx_EC_IABT_LOW // instruction abort in EL0
b.eq el0_ia
cmp x24, #ESR_ELx_EC_FP_ASIMD // FP/ASIMD access
- b.eq el0_fpsimd_acc
+ b.eq el0_fpsimd_acc_compat
cmp x24, #ESR_ELx_EC_FP_EXC32 // FP/ASIMD exception
b.eq el0_fpsimd_exc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
@@ -565,6 +565,17 @@ el0_fpsimd_acc:
mov x1, sp
bl do_fpsimd_acc
b ret_to_user
+el0_fpsimd_acc_compat:
+ /*
+ * Floating Point or Advanced SIMD access
+ */
+ enable_dbg
+ ct_user_exit
+ mov x0, x25
+ mov x1, sp
+ bl do_fpsimd_acc_compat
+ b ret_to_user
+
el0_fpsimd_exc:
/*
* Floating Point or Advanced SIMD exception
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index acc1afd5c749..2ab83aaf4342 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -88,14 +88,23 @@
* whatever is in the FPSIMD registers is not saved to memory, but discarded.
*/
static DEFINE_PER_CPU(struct fpsimd_state *, fpsimd_last_state);
+static DEFINE_PER_CPU(int, fpsimd_stg_enable);
/*
* Trapped FP/ASIMD access.
*/
void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs)
{
- /* TODO: implement lazy context saving/restoring */
- WARN_ON(1);
+ fpsimd_disable_trap();
+ fpsimd_settings_disable();
+ this_cpu_write(fpsimd_stg_enable, 0);
+}
+
+void do_fpsimd_acc_compat(unsigned int esr, struct pt_regs *regs)
+{
+ fpsimd_disable_trap();
+ fpsimd_settings_enable();
+ this_cpu_write(fpsimd_stg_enable, 1);
}
/*
@@ -135,6 +144,11 @@ void fpsimd_thread_switch(struct task_struct *next)
if (current->mm && !test_thread_flag(TIF_FOREIGN_FPSTATE))
fpsimd_save_state(&current->thread.fpsimd_state);
+ if (__this_cpu_read(fpsimd_stg_enable)) {
+ fpsimd_settings_disable();
+ this_cpu_write(fpsimd_stg_enable, 0);
+ }
+
if (next->mm) {
/*
* If we are switching to a task whose most recent userland
@@ -152,6 +166,11 @@ void fpsimd_thread_switch(struct task_struct *next)
else
set_ti_thread_flag(task_thread_info(next),
TIF_FOREIGN_FPSTATE);
+
+ if (test_ti_thread_flag(task_thread_info(next), TIF_32BIT))
+ fpsimd_enable_trap();
+ else
+ fpsimd_disable_trap();
}
}