aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2014-02-24 09:26:27 -0500
committerArd Biesheuvel <ard.biesheuvel@linaro.org>2014-05-08 05:31:41 -0400
commitc51f92693c35c141cf7d9b7e2fcbb81128324eb4 (patch)
tree940006e10b6aa199babdbc16da334713682174b8 /arch
parent0567f5facbdf04806a37ef521dd0893159fde715 (diff)
arm64: add abstractions for FPSIMD state manipulation
There are two tacit assumptions in the FPSIMD handling code that will no longer hold after the next patch that optimizes away some FPSIMD state restores: . the FPSIMD registers of this CPU contain the userland FPSIMD state of task 'current'; . when switching to a task, its FPSIMD state will always be restored from memory. This patch adds the following functions to abstract away from straight FPSIMD register file saves and restores: - fpsimd_preserve_current_state -> ensure current's FPSIMD state is saved - fpsimd_update_current_state -> replace current's FPSIMD state Where necessary, the signal handling and fork code are updated to use the above wrappers instead of poking into the FPSIMD registers directly. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm64/include/asm/fpsimd.h3
-rw-r--r--arch/arm64/kernel/fpsimd.c20
-rw-r--r--arch/arm64/kernel/process.c2
-rw-r--r--arch/arm64/kernel/signal.c9
-rw-r--r--arch/arm64/kernel/signal32.c9
5 files changed, 30 insertions, 13 deletions
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index c43b4ac13008..f4e524b67e91 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -58,6 +58,9 @@ extern void fpsimd_load_state(struct fpsimd_state *state);
58extern void fpsimd_thread_switch(struct task_struct *next); 58extern void fpsimd_thread_switch(struct task_struct *next);
59extern void fpsimd_flush_thread(void); 59extern void fpsimd_flush_thread(void);
60 60
61extern void fpsimd_preserve_current_state(void);
62extern void fpsimd_update_current_state(struct fpsimd_state *state);
63
61#endif 64#endif
62 65
63#endif 66#endif
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 4aef42a04bdc..8a97163debc7 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -87,6 +87,26 @@ void fpsimd_flush_thread(void)
87 preempt_enable(); 87 preempt_enable();
88} 88}
89 89
90/*
91 * Save the userland FPSIMD state of 'current' to memory
92 */
93void fpsimd_preserve_current_state(void)
94{
95 preempt_disable();
96 fpsimd_save_state(&current->thread.fpsimd_state);
97 preempt_enable();
98}
99
100/*
101 * Load an updated userland FPSIMD state for 'current' from memory
102 */
103void fpsimd_update_current_state(struct fpsimd_state *state)
104{
105 preempt_disable();
106 fpsimd_load_state(state);
107 preempt_enable();
108}
109
90#ifdef CONFIG_KERNEL_MODE_NEON 110#ifdef CONFIG_KERNEL_MODE_NEON
91 111
92/* 112/*
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 6391485f342d..c5693163408c 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -205,7 +205,7 @@ void release_thread(struct task_struct *dead_task)
205 205
206int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 206int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
207{ 207{
208 fpsimd_save_state(&current->thread.fpsimd_state); 208 fpsimd_preserve_current_state();
209 *dst = *src; 209 *dst = *src;
210 return 0; 210 return 0;
211} 211}
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 890a591f75dd..06448a77ff53 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -51,7 +51,7 @@ static int preserve_fpsimd_context(struct fpsimd_context __user *ctx)
51 int err; 51 int err;
52 52
53 /* dump the hardware registers to the fpsimd_state structure */ 53 /* dump the hardware registers to the fpsimd_state structure */
54 fpsimd_save_state(fpsimd); 54 fpsimd_preserve_current_state();
55 55
56 /* copy the FP and status/control registers */ 56 /* copy the FP and status/control registers */
57 err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs)); 57 err = __copy_to_user(ctx->vregs, fpsimd->vregs, sizeof(fpsimd->vregs));
@@ -86,11 +86,8 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
86 __get_user_error(fpsimd.fpcr, &ctx->fpcr, err); 86 __get_user_error(fpsimd.fpcr, &ctx->fpcr, err);
87 87
88 /* load the hardware registers from the fpsimd_state structure */ 88 /* load the hardware registers from the fpsimd_state structure */
89 if (!err) { 89 if (!err)
90 preempt_disable(); 90 fpsimd_update_current_state(&fpsimd);
91 fpsimd_load_state(&fpsimd);
92 preempt_enable();
93 }
94 91
95 return err ? -EFAULT : 0; 92 return err ? -EFAULT : 0;
96} 93}
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index b3fc9f5ec6d3..ac7e237d0bda 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -219,7 +219,7 @@ static int compat_preserve_vfp_context(struct compat_vfp_sigframe __user *frame)
219 * Note that this also saves V16-31, which aren't visible 219 * Note that this also saves V16-31, which aren't visible
220 * in AArch32. 220 * in AArch32.
221 */ 221 */
222 fpsimd_save_state(fpsimd); 222 fpsimd_preserve_current_state();
223 223
224 /* Place structure header on the stack */ 224 /* Place structure header on the stack */
225 __put_user_error(magic, &frame->magic, err); 225 __put_user_error(magic, &frame->magic, err);
@@ -282,11 +282,8 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
282 * We don't need to touch the exception register, so 282 * We don't need to touch the exception register, so
283 * reload the hardware state. 283 * reload the hardware state.
284 */ 284 */
285 if (!err) { 285 if (!err)
286 preempt_disable(); 286 fpsimd_update_current_state(&fpsimd);
287 fpsimd_load_state(&fpsimd);
288 preempt_enable();
289 }
290 287
291 return err ? -EFAULT : 0; 288 return err ? -EFAULT : 0;
292} 289}