summaryrefslogtreecommitdiff
path: root/include/task.h
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-04-15 13:53:57 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-04-18 18:58:36 +0000
commitb610695b61db3b3784e2a516c91f429139616100 (patch)
treedd381367d143e3531080bd2dc7caf85a309f4fe2 /include/task.h
parentd899fdaaeef175e97923b954342dad3a33c5c387 (diff)
downloadchrome-ec-b610695b61db3b3784e2a516c91f429139616100.tar.gz
cortex-m: store FPU regs on context switch
Added storing of FPU regs on context switches when CONFIG_FPU is defined. On context switches, EXC_RETURN[4] is checked in order to tell which tasks have used floating point and which have not. The FPU regs are only stored on task stacks for tasks that use the floating point. Tasks that use floating point will therefore require roughly an additional 128 bytes of stack space, and context switches will take about 32 clock cycles longer for each task involved in the switch that uses FP. For tasks that don't use floating point, the stack usage actually decreases by 64 bytes because previously we were reserving stack space for FPU regs S0-S15 on every context switch for every task, even though we weren't doing anything with them. If a task only uses the FPU for a brief window, it can call task_clear_fp_used() in order to clear the FP used bit so that context switches using that task will not backup FP regs anymore. BUG=chrome-os-partner:27971 BRANCH=none TEST=Tested on glimmer and peppy. Added the following code, which uses the FPU in both the hooks task and the console task. Note, I tested this for a handful of registers, notably registers in the group s0-s15 which are backed up by lazy stacking, and registers in the group s16-s31 which are backed up manually. float dummy = 2.0f; static void hook_fpu(void) { union { float f; int i; } tmp; /* do a dummy FP calculation to set CONTROL.FPCA high. */ dummy = 2.3f*7.8f; /* read and print FP reg. */ asm volatile("vmov %0, s29" : "=r"(tmp.f)); ccprintf("Hook float 0x%08x\n", tmp.i); /* write FP reg. */ tmp.i = 0x1234; asm volatile("vmov s29, %0" : : "r"(tmp.f)); } DECLARE_HOOK(HOOK_SECOND, hook_fpu, HOOK_PRIO_DEFAULT); static int command_fpu_test(int argc, char **argv) { union { float f; int i; } tmp; /* do a dummy FP calculation to set CONTROL.FPCA high. */ dummy = 2.7f*7.8f; /* read and print FP reg. */ asm volatile("vmov %0, s29" : "=r"(tmp.f)); ccprintf("Console float 0x%08x\n", tmp.i); if (argc == 2) { char *e; tmp.i = strtoi(argv[1], &e, 0); if (*e) return EC_ERROR_PARAM1; /* write FP reg. */ asm volatile("vmov s29, %0" : : "r"(tmp.f)); } else { task_clear_fp_used(); } return EC_SUCCESS; } DECLARE_CONSOLE_COMMAND(fputest, command_fpu_test, "", "", NULL); When you call fputest 5 from EC console before this CL, then on the next HOOK_SECOND, the value of register s29 is 5, instead of 0x1234 because register s29 is not saved on context switches: Hook float 0x00001234 > fputest 5 Console float 0x00001234 Hook float 0x00000005 When this CL is in use, the register holds the correct value for each task: Hook float 0x00001234 > fputest 5 Console float 0x00001234 Hook float 0x00001234 > fputest Console float 0x00000005 Hook float 0x00001234 Change-Id: Ifb1b5cbf1c6fc9193f165f8d69c96443b35bf981 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/194949 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'include/task.h')
-rw-r--r--include/task.h9
1 files changed, 9 insertions, 0 deletions
diff --git a/include/task.h b/include/task.h
index 00368fbc34..1d80a0b2f7 100644
--- a/include/task.h
+++ b/include/task.h
@@ -171,6 +171,15 @@ int task_start(void);
*/
int task_start_called(void);
+#ifdef CONFIG_FPU
+/**
+ * Clear floating-point used flag for currently executing task. This means the
+ * FPU regs will not be stored on context switches until the next time floating
+ * point is used for currently executing task.
+ */
+void task_clear_fp_used(void);
+#endif
+
/**
* Enable an interrupt.
*/