diff options
author | Hyungwoo Yang <hyungwoo.yang@intel.com> | 2019-01-30 12:30:47 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-02-26 05:09:12 -0800 |
commit | decc9452e981a7c8ce5c6b8983061a054057c615 (patch) | |
tree | eaea7bba6491f96bc06a77e2af2fd43d4b210894 | |
parent | 0a3f44e4f508d0c6a96519e6db97b2f2fd4bfb23 (diff) | |
download | chrome-ec-decc9452e981a7c8ce5c6b8983061a054057c615.tar.gz |
ish: save/restore FPU context only for the task uses FPU
Currently we save/retore FPU H/W context for every task on
every contxt switch. This hurts overall performance of ISH.
This patch allows save and restore FPU H/W context only for
a task that declares it uses FPU.
BRANCH=none
BUG=none
TEST=verified in Atlas platform
Change-Id: Ic2f0bbf59f655661e2dd788c688edc4e83068c1c
Signed-off-by: Hyungwoo Yang <hyungwoo.yang@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/1448818
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Hyungwoo Yang <hyungwoo.yang@intel.corp-partner.google.com>
Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r-- | board/arcada_ish/ec.tasklist | 10 | ||||
-rw-r--r-- | board/atlas_ish/ec.tasklist | 14 | ||||
-rw-r--r-- | core/minute-ia/config_core.h | 5 | ||||
-rw-r--r-- | core/minute-ia/irq_handler.h | 14 | ||||
-rw-r--r-- | core/minute-ia/switch.S | 17 | ||||
-rw-r--r-- | core/minute-ia/task.c | 33 | ||||
-rw-r--r-- | core/minute-ia/task_defs.h | 18 | ||||
-rw-r--r-- | include/task_filter.h | 16 | ||||
-rw-r--r-- | include/task_id.h | 2 | ||||
-rw-r--r-- | util/export_taskinfo.c | 8 |
10 files changed, 100 insertions, 37 deletions
diff --git a/board/arcada_ish/ec.tasklist b/board/arcada_ish/ec.tasklist index f384af4d8b..b6e2cf28d5 100644 --- a/board/arcada_ish/ec.tasklist +++ b/board/arcada_ish/ec.tasklist @@ -8,15 +8,17 @@ * * The first one has the lowest priority. * - * For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and - * TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries, + * For each task, use the macro TASK_ALWAYS(n, r, d, s, f) for base tasks and + * TASK_NOTEST(n, r, d, s, f) for tasks that can be excluded in test binaries, * where : * 'n' in the name of the task * 'r' in the main routine of the task * 'd' in an opaque parameter passed to the routine at startup * 's' is the stack size in bytes; must be a multiple of 8 + * 'f' is the bit flags for the platform specific information + * - MIA_TASK_FLAG_USE_FPU : bit 0, task uses FPU H/W */ #define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, HUGE_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) + TASK_ALWAYS(HOOKS, hook_task, NULL, HUGE_TASK_STACK_SIZE, 0) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE, 0) diff --git a/board/atlas_ish/ec.tasklist b/board/atlas_ish/ec.tasklist index 4fa8b59582..4486b508e6 100644 --- a/board/atlas_ish/ec.tasklist +++ b/board/atlas_ish/ec.tasklist @@ -8,17 +8,19 @@ * * The first one has the lowest priority. * - * For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and - * TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries, + * For each task, use the macro TASK_ALWAYS(n, r, d, s, f) for base tasks and + * TASK_NOTEST(n, r, d, s, f) for tasks that can be excluded in test binaries, * where : * 'n' in the name of the task * 'r' in the main routine of the task * 'd' in an opaque parameter passed to the routine at startup * 's' is the stack size in bytes; must be a multiple of 8 + * 'f' is the bit flags for the platform specific information + * - MIA_TASK_FLAG_USE_FPU : bit 0, task uses FPU H/W */ #define CONFIG_TASK_LIST \ - TASK_ALWAYS(HOOKS, hook_task, NULL, HUGE_TASK_STACK_SIZE) \ - TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ - TASK_ALWAYS(HECI_RX, heci_rx_task, NULL, HUGE_TASK_STACK_SIZE) \ - TASK_ALWAYS(IPC_MNG, ipc_mng_task, NULL, LARGER_TASK_STACK_SIZE) + TASK_ALWAYS(HOOKS, hook_task, NULL, HUGE_TASK_STACK_SIZE, 0) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE, 0) \ + TASK_ALWAYS(HECI_RX, heci_rx_task, NULL, HUGE_TASK_STACK_SIZE, 0) \ + TASK_ALWAYS(IPC_MNG, ipc_mng_task, NULL, LARGER_TASK_STACK_SIZE, 0) diff --git a/core/minute-ia/config_core.h b/core/minute-ia/config_core.h index 20f4404d38..47121642a4 100644 --- a/core/minute-ia/config_core.h +++ b/core/minute-ia/config_core.h @@ -26,4 +26,9 @@ #define ASM_LOCK_PREFIX #endif +/* + * Flag indicates the task uses FPU H/W + */ +#define MIA_TASK_FLAG_USE_FPU 0x00000001 + #endif /* __CROS_EC_CONFIG_CORE_H */ diff --git a/core/minute-ia/irq_handler.h b/core/minute-ia/irq_handler.h index c561ee472b..4df2b14da6 100644 --- a/core/minute-ia/irq_handler.h +++ b/core/minute-ia/irq_handler.h @@ -9,10 +9,20 @@ #define __CROS_EC_IRQ_HANDLER_H #include "registers.h" +#include "task_defs.h" #ifdef CONFIG_FPU -#define save_fpu_ctx "fnsave 20(%eax)\n" -#define rstr_fpu_ctx "frstor 20(%eax)\n" +#define save_fpu_ctx "movl "USE_FPU_OFFSET_STR"(%eax), %ebx\n" \ + "test %ebx, %ebx\n" \ + "jz 9f\n" \ + "fnsave "FPU_CTX_OFFSET_STR"(%eax)\n" \ + "9:\n" + +#define rstr_fpu_ctx "movl "USE_FPU_OFFSET_STR"(%eax), %ebx\n" \ + "test %ebx, %ebx\n" \ + "jz 9f\n" \ + "frstor "FPU_CTX_OFFSET_STR"(%eax)\n" \ + "9:\n" #else #define save_fpu_ctx #define rstr_fpu_ctx diff --git a/core/minute-ia/switch.S b/core/minute-ia/switch.S index eed2f7929f..27aba1a7cc 100644 --- a/core/minute-ia/switch.S +++ b/core/minute-ia/switch.S @@ -33,7 +33,11 @@ __task_start: movl current_task, %eax movl (%eax), %esp #ifdef CONFIG_FPU - frstor 20(%eax) + movl USE_FPU_OFFSET(%eax), %ebx + test %ebx, %ebx + jz 1f + frstor FPU_CTX_OFFSET(%eax) + 1: #endif movl $0x1, (%ebx) # first task is ready. set start_called = 1 popa @@ -112,7 +116,11 @@ __switchto: movl current_task, %eax #ifdef CONFIG_FPU - fnsave 20(%eax) # Save current FPU context at current->fp_ctx + movl USE_FPU_OFFSET(%eax), %ebx + test %ebx, %ebx + jz 2f + fnsave FPU_CTX_OFFSET(%eax) # Save current FPU context(current->fp_ctx) + 2: #endif # Save SP of current task and switch to new task @@ -122,7 +130,10 @@ __switchto: movl (%eax), %esp #ifdef CONFIG_FPU - frstor 20(%eax) # Restore next FPU context + movl USE_FPU_OFFSET(%eax), %ebx + test %ebx, %ebx + jz 1f + frstor FPU_CTX_OFFSET(%eax) # Restore next FPU context #endif 1: diff --git a/core/minute-ia/task.c b/core/minute-ia/task.c index 2836d40975..9975cc62d7 100644 --- a/core/minute-ia/task.c +++ b/core/minute-ia/task.c @@ -26,7 +26,7 @@ #define STACK_UNUSED_VALUE 0xdeadd00d /* declare task routine prototypes */ -#define TASK(n, r, d, s) void r(void *); +#define TASK(n, r, d, s, f) void r(void *); void __idle(void); CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST @@ -36,7 +36,7 @@ CONFIG_TEST_TASK_LIST extern volatile uint32_t __in_isr; /* Task names for easier debugging */ -#define TASK(n, r, d, s) #n, +#define TASK(n, r, d, s, f) #n, static const char * const task_names[] = { "<< idle >>", CONFIG_TASK_LIST @@ -90,17 +90,19 @@ static void task_exit_trap(void) } /* Startup parameters for all tasks. */ -#define TASK(n, r, d, s) { \ +#define TASK(n, r, d, s, f) { \ .r0 = (uint32_t)d, \ .pc = (uint32_t)r, \ .stack_size = s, \ + .flags = f, \ }, static const struct { uint32_t r0; uint32_t pc; uint16_t stack_size; + uint32_t flags; } tasks_init[] = { - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) + TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE, 0) CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST }; @@ -115,9 +117,9 @@ BUILD_ASSERT(TASK_ID_COUNT < (1 << (sizeof(task_id_t) * 8))); /* Stacks for all tasks */ -#define TASK(n, r, d, s) + s +#define TASK(n, r, d, s, f) + s uint8_t task_stacks[0 - TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE) + TASK(IDLE, __idle, 0, IDLE_TASK_STACK_SIZE, 0) CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST ] __aligned(8); @@ -474,10 +476,18 @@ void task_print_list(void) { int i; +#ifdef CONFIG_FPU + ccputs("Task Ready Name Events Time (s) " + " StkUsed UseFPU\n"); +#else ccputs("Task Ready Name Events Time (s) StkUsed\n"); +#endif for (i = 0; i < TASK_ID_COUNT; i++) { char is_ready = (tasks_ready & (1<<i)) ? 'R' : ' '; +#ifdef CONFIG_FPU + char use_fpu = tasks[i].use_fpu ? 'Y' : 'N'; +#endif uint32_t *sp; int stackused = tasks_init[i].stack_size; @@ -487,9 +497,16 @@ void task_print_list(void) sp++) stackused -= sizeof(uint32_t); +#ifdef CONFIG_FPU + ccprintf("%4d %c %-16s %08x %11.6ld %3d/%3d %c\n", i, is_ready, + task_names[i], tasks[i].events, tasks[i].runtime, + stackused, tasks_init[i].stack_size, use_fpu); +#else ccprintf("%4d %c %-16s %08x %11.6ld %3d/%3d\n", i, is_ready, task_names[i], tasks[i].events, tasks[i].runtime, stackused, tasks_init[i].stack_size); +#endif + cflush(); } } @@ -606,6 +623,9 @@ void task_pre_init(void) /* Copy default x86 FPU state for each task */ memcpy(tasks[i].fp_ctx, default_fp_ctx, sizeof(default_fp_ctx)); + + if (tasks_init[i].flags & MIA_TASK_FLAG_USE_FPU) + tasks[i].use_fpu = 1; #endif /* Fill unused stack; also used to detect stack overflow. */ for (sp = stack_next; sp < (uint32_t *)tasks[i].sp; sp++) @@ -618,7 +638,6 @@ void task_pre_init(void) /* Initialize IRQs */ init_interrupts(); - } void task_clear_fp_used(void) diff --git a/core/minute-ia/task_defs.h b/core/minute-ia/task_defs.h index 2ec33e5c98..15aca6b8b5 100644 --- a/core/minute-ia/task_defs.h +++ b/core/minute-ia/task_defs.h @@ -6,8 +6,21 @@ #ifndef __CROS_EC_TASK_DEFS_H #define __CROS_EC_TASK_DEFS_H -#define FPU_CTX_SZ 108 /* 28 bytes header + 80 bytes registers */ -#define FPU_CTX_OFFSET 20 /* offsetof(task_, fp_ctx) */ +#ifdef CONFIG_FPU +#define FPU_CTX_SZ 108 /* 28 bytes header + 80 bytes registers */ +#define USE_FPU_OFFSET 20 /* offsetof(task_, use_fpu */ +#define FPU_CTX_OFFSET 24 /* offsetof(task_, fp_ctx) */ + +/* + * defines for inline asm + */ +#ifndef __ASSEMBLER__ +#include "common.h" + +#define USE_FPU_OFFSET_STR STRINGIFY(USE_FPU_OFFSET) /* "20" */ +#define FPU_CTX_OFFSET_STR STRINGIFY(FPU_CTX_OFFSET) /* "24" */ +#endif +#endif /* CONFIG_FPU */ #ifndef __ASSEMBLER__ typedef union { @@ -21,6 +34,7 @@ typedef union { uint64_t runtime; /* Time spent in task */ uint32_t *stack; /* Start of stack */ #ifdef CONFIG_FPU + uint32_t use_fpu; /* set if task uses FPU */ uint8_t fp_ctx[FPU_CTX_SZ]; /* x87 FPU context */ #endif }; diff --git a/include/task_filter.h b/include/task_filter.h index af80194e7f..b83b530f52 100644 --- a/include/task_filter.h +++ b/include/task_filter.h @@ -13,21 +13,21 @@ #define TASK_NOTEST_RO TASK_NOTEST #define TASK_TEST_RO TASK_TEST #define TASK_ALWAYS_RO TASK_ALWAYS -#define TASK_NOTEST_RW(n, r, d, s) -#define TASK_TEST_RW(n, r, d, s) -#define TASK_ALWAYS_RW(n, r, d, s) +#define TASK_NOTEST_RW(...) +#define TASK_TEST_RW(...) +#define TASK_ALWAYS_RW(...) #else /* SECTION_IS_RW */ #define TASK_NOTEST_RW TASK_NOTEST #define TASK_TEST_RW TASK_TEST #define TASK_ALWAYS_RW TASK_ALWAYS -#define TASK_NOTEST_RO(n, r, d, s) -#define TASK_TEST_RO(n, r, d, s) -#define TASK_ALWAYS_RO(n, r, d, s) +#define TASK_NOTEST_RO(...) +#define TASK_TEST_RO(...) +#define TASK_ALWAYS_RO(...) #endif /* excludes non-base tasks for test build */ #ifdef TEST_BUILD -#define TASK_NOTEST(n, r, d, s) +#define TASK_NOTEST(...) #define TASK_TEST TASK #else #define TASK_NOTEST TASK @@ -42,7 +42,7 @@ /* If included directly from Makefile, dump task list. */ #ifdef _MAKEFILE -#define TASK(n, r, d, s) n +#define TASK(n, ...) n CONFIG_TASK_LIST CONFIG_TEST_TASK_LIST CONFIG_CTS_TASK_LIST #endif diff --git a/include/task_id.h b/include/task_id.h index b4ecf9bf82..6cb23a2822 100644 --- a/include/task_id.h +++ b/include/task_id.h @@ -35,7 +35,7 @@ typedef uint8_t task_id_t; * TASK_ID_<taskname> where <taskname> is the first parameter passed to the * TASK macro in the TASK_LIST file. */ -#define TASK(n, r, d, s) TASK_ID_##n, +#define TASK(n, ...) TASK_ID_##n, enum { TASK_ID_IDLE, /* CONFIG_TASK_LIST is a macro coming from the BOARD_TASK_LIST file */ diff --git a/util/export_taskinfo.c b/util/export_taskinfo.c index 19109f131e..4c09bafb90 100644 --- a/util/export_taskinfo.c +++ b/util/export_taskinfo.c @@ -25,10 +25,10 @@ struct taskinfo { uint32_t stack_size; }; -#define TASK(n, r, d, s) { \ - .name = #n, \ - .routine = #r, \ - .stack_size = s, \ +#define TASK(n, r, d, s, ...) { \ + .name = #n, \ + .routine = #r, \ + .stack_size = s, \ }, static const struct taskinfo taskinfos[] = { CONFIG_TASK_LIST |