1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-13 13:55:50 +00:00

feat(core): introduce systask id & task count limit

[no changelog]
This commit is contained in:
cepetr 2025-03-20 15:23:51 +01:00
parent 7cbbfb2adc
commit 604a8cbba7
3 changed files with 46 additions and 8 deletions

View File

@ -17,8 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TREZORHAL_SYSTASK_H
#define TREZORHAL_SYSTASK_H
#pragma once
#include <trezor_types.h>
@ -97,6 +96,12 @@ typedef void (*systask_error_handler_t)(const systask_postmortem_t* pminfo);
#ifdef KERNEL_MODE
// Maximum number of tasks that can be created
#define SYSTASK_MAX_TASKS 2
// Zero-based task ID (up SYSTASK_MAX_TASKS - 1)
typedef uint8_t systask_id_t;
// Task context used by the kernel to save the state of each task
// when switching between them
typedef struct {
@ -111,6 +116,8 @@ typedef struct {
// Set to nonzero, if the task is killed
uint32_t killed;
// Task id
systask_id_t id;
// MPU mode the task is running in
mpu_mode_t mpu_mode;
// Task post-mortem information
@ -134,7 +141,7 @@ void systask_yield_to(systask_t* task);
// Initializes a task with the given stack pointer, stack size
//
// The task must be not be running when the function is called
void systask_init(systask_t* task, uint32_t stack_ptr, uint32_t stack_size,
bool systask_init(systask_t* task, uint32_t stack_ptr, uint32_t stack_size,
void* context);
// Pushes data onto the stack of the task
@ -154,6 +161,9 @@ void systask_pop_data(systask_t* task, size_t size);
bool systask_push_call(systask_t* task, void* fn, uint32_t arg1, uint32_t arg2,
uint32_t arg3);
// Gets the Id (zero-based index up SYSTASK_MAX_TASKS - 1) of the given task
systask_id_t systask_id(systask_t* task);
// Terminates the task with the given exit code
//
// If the task is not specified (NULL), it's automatically determined:
@ -181,5 +191,3 @@ void systask_exit_fatal(systask_t* task, const char* message,
int line);
#endif // KERNEL_MODE
#endif // TREZORHAL_SYSTASK_H

View File

@ -56,8 +56,10 @@ bool applet_reset(applet_t* applet, uint32_t cmd, const void* arg,
applet_clear_memory(applet);
// Reset the applet task (stack pointer, etc.)
systask_init(&applet->task, applet->header->stack.start,
applet->header->stack.size, applet);
if (!systask_init(&applet->task, applet->header->stack.start,
applet->header->stack.size, applet)) {
return false;
}
// Copy the arguments onto the applet stack
void* arg_copy = NULL;

View File

@ -53,6 +53,8 @@ typedef struct {
systask_t* active_task;
// Task to be scheduled next
systask_t* waiting_task;
// Bitmap of used task IDs
uint32_t task_id_map;
} systask_scheduler_t;
// Global task manager state
@ -61,8 +63,10 @@ static systask_scheduler_t g_systask_scheduler = {
// to function correctly before the scheduler is initialized.
.active_task = &g_systask_scheduler.kernel_task,
.waiting_task = &g_systask_scheduler.kernel_task,
.task_id_map = 0x00000001, // Kernel task is always present
.kernel_task = {
.sp_lim = (uint32_t)&_stack_section_start,
.id = 0, // Kernel task ID == 0
}};
void systask_scheduler_init(systask_error_handler_t error_handler) {
@ -73,6 +77,7 @@ void systask_scheduler_init(systask_error_handler_t error_handler) {
scheduler->error_handler = error_handler;
scheduler->active_task = &scheduler->kernel_task;
scheduler->waiting_task = scheduler->active_task;
scheduler->task_id_map = 0x00000001; // Kernel task is always present
scheduler->kernel_task.sp_lim = (uint32_t)&_stack_section_start;
@ -117,16 +122,36 @@ void systask_yield_to(systask_t* task) {
systask_yield();
}
void systask_init(systask_t* task, uint32_t stack_ptr, uint32_t stack_size,
static systask_id_t systask_get_unused_id(void) {
systask_id_t id = 0;
while (++id < SYSTASK_MAX_TASKS) {
if ((g_systask_scheduler.task_id_map & (1 << id)) == 0) {
break;
}
}
return id;
}
bool systask_init(systask_t* task, uint32_t stack_ptr, uint32_t stack_size,
void* applet) {
systask_id_t id = systask_get_unused_id();
if (id >= SYSTASK_MAX_TASKS) {
return false;
}
memset(task, 0, sizeof(systask_t));
task->sp = stack_ptr + stack_size;
task->sp_lim = stack_ptr + 256;
task->exc_return = 0xFFFFFFED; // Thread mode, use PSP, pop FP context
task->id = id;
task->mpu_mode = MPU_MODE_APP;
task->applet = applet;
return true;
}
systask_id_t systask_id(const systask_t* task) { return task->id; }
uint32_t* systask_push_data(systask_t* task, const void* data, size_t size) {
if (task->sp < task->sp_lim) {
// Stack overflow
@ -211,6 +236,9 @@ static void systask_kill(systask_t* task) {
// if it returns. Neither is expected to happen.
reboot_device();
} else if (task == scheduler->active_task) {
// Free task ID
scheduler->task_id_map &= ~(1 << task->id);
// Switch to the kernel task
systask_yield_to(&scheduler->kernel_task);
}