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>
This commit is contained in:
Shawn Nematbakhsh
2017-06-16 09:37:31 -07:00
committed by chrome-bot
parent 90167c1764
commit 8a16e6483a
7 changed files with 43 additions and 24 deletions

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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);
}
/*****************************************************************************/