diff options
author | Shawn Nematbakhsh <shawnn@chromium.org> | 2017-06-16 09:37:31 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-06-19 15:33:10 -0700 |
commit | 8a16e6483ab80a85af44e8ba164e5e91a51ec43a (patch) | |
tree | f466b3e4ba712c0b6a0d5510d4aaff0a937e5005 | |
parent | 90167c1764ab7c532b121bd08990b81631a3c896 (diff) | |
download | chrome-ec-8a16e6483ab80a85af44e8ba164e5e91a51ec43a.tar.gz |
task: Wait for HOOK_INIT completion before scheduling tasks
Until HOOK_INIT has completed, do not allow any tasks other than HOOKS
or IDLE to be scheduled. Programmers often make the assumption that
a HOOK_INIT function is guaranteed to be run before task code that depends
on it, so let's make it so.
BUG=chromium:649398
BRANCH=None
TEST=Manual on kevin, compare boot without patch:
...
[0.004 power state 0 = G3, in 0x0008] <-- from chipset task
RTC: 0x00000000 (0.00 s)
[0.004 power state 4 = G3->S5, in 0x0008]
RTC: 0x00000000 (0.00 s)
[0.005 clear MKBP fifo]
[0.006 clear MKBP fifo]
[0.006 KB init state: ... <-- from keyscan task
[0.012 SW 0x05]
[0.155 hash start 0x00020000 0x00019a38]
[0.158 HOOK_INIT DONE!]
... to boot with patch:
...
RTC: 0x58cc614c (1489789260.00 s)
[0.004 clear MKBP fifo]
[0.005 clear MKBP fifo]
[0.010 SW 0x05]
[0.155 hash start 0x00020000 0x000198e0]
[0.157 HOOK_INIT DONE!]
...
Also, verify kevin boots to OS and is generally functional through
sysjump and basic tasks, and verify elm (stm32f0 / cortex-m0) boots.
Change-Id: If56fab05ce9b9650feb93c5cfc2d084aa281e622
Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/456628
Commit-Ready: Shawn N <shawnn@chromium.org>
Tested-by: Shawn N <shawnn@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | common/console.c | 3 | ||||
-rw-r--r-- | core/cortex-m/task.c | 14 | ||||
-rw-r--r-- | core/cortex-m0/switch.S | 2 | ||||
-rw-r--r-- | core/cortex-m0/task.c | 14 | ||||
-rw-r--r-- | core/minute-ia/task.c | 19 | ||||
-rw-r--r-- | core/nds32/task.c | 12 | ||||
-rw-r--r-- | power/common.c | 3 |
7 files changed, 43 insertions, 24 deletions
diff --git a/common/console.c b/common/console.c index 402befc622..bb4195d584 100644 --- a/common/console.c +++ b/common/console.c @@ -647,8 +647,7 @@ void console_has_input(void) #endif /* Wake up the console task */ - if (task_start_called()) - task_wake(TASK_ID_CONSOLE); + task_wake(TASK_ID_CONSOLE); } void console_task(void) diff --git a/core/cortex-m/task.c b/core/cortex-m/task.c index f23b8142ff..6b978c9d33 100644 --- a/core/cortex-m/task.c +++ b/core/cortex-m/task.c @@ -167,6 +167,12 @@ static int need_resched_or_profiling; * make a call to enable all tasks. */ static uint32_t tasks_ready = (1 << TASK_ID_HOOKS); +/* + * Initially allow only the HOOKS and IDLE task to run, regardless of ready + * status, in order for HOOK_INIT to complete before other tasks. + * task_enable_all_tasks() will open the flood gates. + */ +static uint32_t tasks_enabled = (1 << TASK_ID_HOOKS) | (1 << TASK_ID_IDLE); static int start_called; /* Has task swapping started */ @@ -271,8 +277,8 @@ void svc_handler(int desched, task_id_t resched) ASSERT(resched <= TASK_ID_COUNT); tasks_ready |= 1 << resched; - ASSERT(tasks_ready); - next = __task_id_to_ptr(__fls(tasks_ready)); + ASSERT(tasks_ready & tasks_enabled); + next = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); #ifdef CONFIG_TASK_PROFILING /* Track time in interrupts */ @@ -443,8 +449,8 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) void task_enable_all_tasks(void) { - /* Mark all tasks as ready to run. */ - tasks_ready = (1 << TASK_ID_COUNT) - 1; + /* Mark all tasks as ready and able to run. */ + tasks_ready = tasks_enabled = (1 << TASK_ID_COUNT) - 1; /* Reschedule the highest priority task. */ __schedule(0, 0); } diff --git a/core/cortex-m0/switch.S b/core/cortex-m0/switch.S index 95ea29e765..4b5ae23838 100644 --- a/core/cortex-m0/switch.S +++ b/core/cortex-m0/switch.S @@ -67,7 +67,7 @@ __task_start: adds r2, #17*4 @ put the pointer at the top of the stack movs r1, #0 @ __Schedule parameter : re-schedule nothing msr psp, r2 @ setup a thread stack up to the first context switch - movs r2, #1 + movs r2, #1 @ r2 = TASK_SCHEDULER_INIT isb @ ensure the write is done msr control, r3 movs r3, r0 diff --git a/core/cortex-m0/task.c b/core/cortex-m0/task.c index 8796983127..32f67e0d62 100644 --- a/core/cortex-m0/task.c +++ b/core/cortex-m0/task.c @@ -134,6 +134,12 @@ static task_ *current_task = (task_ *)scratchpad; * make a call to enable all tasks. */ static uint32_t tasks_ready = (1 << TASK_ID_HOOKS); +/* + * Initially allow only the HOOKS and IDLE task to run, regardless of ready + * status, in order for HOOK_INIT to complete before other tasks. + * task_enable_all_tasks() will open the flood gates. + */ +static uint32_t tasks_enabled = (1 << TASK_ID_HOOKS) | (1 << TASK_ID_IDLE); static int start_called; /* Has task swapping started */ @@ -234,8 +240,8 @@ task_ __attribute__((noinline)) *__svc_handler(int desched, task_id_t resched) } tasks_ready |= 1 << resched; - ASSERT(tasks_ready); - next = __task_id_to_ptr(__fls(tasks_ready)); + ASSERT(tasks_ready & tasks_enabled); + next = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); #ifdef CONFIG_TASK_PROFILING /* Track additional time in re-sched exception context */ @@ -442,8 +448,8 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) void task_enable_all_tasks(void) { - /* Mark all tasks as ready to run. */ - tasks_ready = (1 << TASK_ID_COUNT) - 1; + /* Mark all tasks as ready and able to run. */ + tasks_ready = tasks_enabled = (1 << TASK_ID_COUNT) - 1; /* Reschedule the highest priority task. */ __schedule(0, 0); } diff --git a/core/minute-ia/task.c b/core/minute-ia/task.c index 0d131ae318..e3676e292c 100644 --- a/core/minute-ia/task.c +++ b/core/minute-ia/task.c @@ -145,6 +145,12 @@ static int need_resched_or_profiling; * make a call to enable all tasks. */ static uint32_t tasks_ready = (1 << TASK_ID_HOOKS); +/* + * Initially allow only the HOOKS and IDLE task to run, regardless of ready + * status, in order for HOOK_INIT to complete before other tasks. + * task_enable_all_tasks() will open the flood gates. + */ +static uint32_t tasks_enabled = (1 << TASK_ID_HOOKS) | (1 << TASK_ID_IDLE); static int start_called; /* Has task swapping started */ @@ -217,10 +223,6 @@ uint32_t switch_handler(int desched, task_id_t resched) } #endif - /* Stay in hook till task_enable_all_tasks() */ - if (!task_start_called() && tasks_ready > 3) - tasks_ready = 3; - current = current_task; #ifdef CONFIG_DEBUG_STACK_OVERFLOW @@ -242,8 +244,8 @@ uint32_t switch_handler(int desched, task_id_t resched) } tasks_ready |= 1 << resched; - ASSERT(tasks_ready); - next = __task_id_to_ptr(__fls(tasks_ready)); + ASSERT(tasks_ready & tasks_enabled); + next = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); #ifdef CONFIG_TASK_PROFILING /* Track time in interrupts */ @@ -430,9 +432,10 @@ uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) void task_enable_all_tasks(void) { - /* Mark all tasks as ready to run. */ - tasks_ready = (1 << TASK_ID_COUNT) - 1; + /* Mark all tasks as ready and table to run. */ + tasks_ready = tasks_enabled = (1 << TASK_ID_COUNT) - 1; + /* BUG: task_start() was likely already called */ start_called = 1; /* The host OS driver should wait till the FW completes all hook inits. diff --git a/core/nds32/task.c b/core/nds32/task.c index 9310223989..8fab6d1ef8 100644 --- a/core/nds32/task.c +++ b/core/nds32/task.c @@ -159,6 +159,12 @@ int need_resched; * make a call to enable all tasks. */ static uint32_t tasks_ready = (1 << TASK_ID_HOOKS); +/* + * Initially allow only the HOOKS and IDLE task to run, regardless of ready + * status, in order for HOOK_INIT to complete before other tasks. + * task_enable_all_tasks() will open the flood gates. + */ +static uint32_t tasks_enabled = (1 << TASK_ID_HOOKS) | (1 << TASK_ID_IDLE); static int start_called; /* Has task swapping started */ @@ -285,7 +291,7 @@ void __ram_code syscall_handler(int desched, task_id_t resched, int swirq) task_ *next_sched_task(void) { - task_ *new_task = __task_id_to_ptr(__fls(tasks_ready)); + task_ *new_task = __task_id_to_ptr(__fls(tasks_ready & tasks_enabled)); #ifdef CONFIG_TASK_PROFILING if (current_task != new_task) { @@ -526,8 +532,8 @@ void set_int_ctrl(uint32_t val) void task_enable_all_tasks(void) { - /* Mark all tasks are ready to run. */ - tasks_ready = (1 << TASK_ID_COUNT) - 1; + /* Mark all tasks as ready and able to run. */ + tasks_ready = tasks_enabled = (1 << TASK_ID_COUNT) - 1; /* Reschedule the highest priority task. */ __schedule(0, 0, 0); } diff --git a/power/common.c b/power/common.c index c9f58e92db..acca62c6df 100644 --- a/power/common.c +++ b/power/common.c @@ -359,8 +359,7 @@ void chipset_exit_hard_off(void) * pressed. For other states here, to wake the chipset task to trigger * the event for leaving G3 is necessary. */ - if (task_start_called()) - task_wake(TASK_ID_CHIPSET); + task_wake(TASK_ID_CHIPSET); } /*****************************************************************************/ |