1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-08-03 12:28:13 +00:00

feat(core): allow execution of syscalls in thread mode

[no changelog]
This commit is contained in:
cepetr 2025-05-27 11:58:39 +02:00 committed by cepetr
parent a133a01a1f
commit 37b608827c
20 changed files with 420 additions and 118 deletions

View File

@ -28,6 +28,7 @@
#include <sys/applet.h>
#include <sys/bootutils.h>
#include <sys/mpu.h>
#include <sys/syscall_ipc.h>
#include <sys/sysevent.h>
#include <sys/system.h>
#include <sys/systick.h>
@ -191,11 +192,19 @@ void drivers_init() {
// Returns when the coreapp task is terminated
static void kernel_loop(applet_t *coreapp) {
do {
sysevents_t awaited = {0};
sysevents_t awaited = {
.read_ready = 1 << SYSHANDLE_SYSCALL,
.write_ready = 0,
};
sysevents_t signalled = {0};
sysevents_poll(&awaited, &signalled, ticks_timeout(100));
if (signalled.read_ready & (1 << SYSHANDLE_SYSCALL)) {
syscall_ipc_dequeue();
}
} while (applet_is_alive(coreapp));
}

View File

@ -143,7 +143,7 @@ saes_invoke(void) {
// reset the key loaded in SAES
MODIFY_REG(SAES->CR, AES_CR_KEYSEL, CRYP_KEYSEL_NORMAL);
syscall_return_from_callback(sectrue);
svc_return_from_unpriv(sectrue);
return 0;
}

View File

@ -36,20 +36,12 @@
//
// Return values must be copied to `args[0]` and
// `args[1]` (if returning a 64-bit value).
void syscall_handler(uint32_t* args, uint32_t syscall);
// Invokes the application callback from the syscall handler.
//
// This is a *temporary* helper function used to invoke application callbacks
// from the syscall handler. It will be removed once all callback arguments
// are eliminated from syscalls.
uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3,
void* callback);
void syscall_handler(uint32_t* args, uint32_t syscall, void* applet);
// Internal function for returning from an application callback.
// This function is called from an unprivileged app via an SVC call. It restores
// the stack pointer and returns control to the privileged caller.
void return_from_app_callback(uint32_t retval, uint32_t* msp);
void return_from_unpriv(uint32_t retval, uint32_t* msp);
// Invokes an unprivileged function from privileged mode.
//
@ -58,8 +50,6 @@ void return_from_app_callback(uint32_t retval, uint32_t* msp);
// different hardware keys being used in privileged and unprivileged modes).
uint32_t invoke_unpriv(void* func);
#endif // KERNEL_MODE
// Returns from an unprivileged callback.
//
// Same as `invoke_unpriv`, this function should be removed once
@ -67,10 +57,12 @@ uint32_t invoke_unpriv(void* func);
// unprivileged mode.
static void inline __attribute__((no_stack_protector))
syscall_return_from_callback(uint32_t retval) {
svc_return_from_unpriv(uint32_t retval) {
register uint32_t r0 __asm__("r0") = retval;
__asm__ volatile("svc %[svid]\n"
:
: [svid] "i"(SVC_CALLBACK_RETURN), "r"(r0)
: "memory");
}
#endif // KERNEL_MODE

View File

@ -0,0 +1,46 @@
/*
* This file is part of the Trezor project, https://trezor.io/
*
* Copyright (c) SatoshiLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifdef KERNEL
#include <trezor_types.h>
#include <sys/syscall_numbers.h>
// Initializes IPC for syscalls
bool syscall_ipc_init(void);
// Enqueues a syscall for processing in the kernel event loop
//
// Queued syscalls are signalled to the kernel task by
// asserting SYSEVENT_SYSCALL.
//
// The function may be called only from kernel handler mode
// (respectively from SVCall handler).
void syscall_ipc_enqueue(uint32_t* args, syscall_number_t syscall);
// Dequeues and processed a syscall
//
// Removes the syscall from the queue and executes it. This
// function is intended to be called from the kernel event loop.
void syscall_ipc_dequeue(void);
#endif // KERNEL

View File

@ -19,10 +19,19 @@
#pragma once
// All syscalls with SYSCALL_THREAD_MODE flag are executed
// in kernel thread mode
#define SYSCALL_THREAD_MODE 0x80000000
// Syscall identifiers
typedef enum {
SYSCALL_SYSTEM_EXIT = 1,
// ------------------------------------------------------
// Following syscalls are executed in kernel handler mode
SYSCALL_RETURN_FROM_CALLBACK = 1,
SYSCALL_SYSTEM_EXIT,
SYSCALL_SYSTEM_EXIT_ERROR,
SYSCALL_SYSTEM_EXIT_FATAL,
@ -108,25 +117,6 @@ typedef enum {
SYSCALL_OPTIGA_RANDOM_BUFFER,
SYSCALL_OPTIGA_SET_SEC_MAX,
SYSCALL_STORAGE_INIT,
SYSCALL_STORAGE_WIPE,
SYSCALL_STORAGE_IS_UNLOCKED,
SYSCALL_STORAGE_LOCK,
SYSCALL_STORAGE_UNLOCK,
SYSCALL_STORAGE_HAS_PIN,
SYSCALL_STORAGE_PIN_FAILS_INCREASE,
SYSCALL_STORAGE_GET_PIN_REM,
SYSCALL_STORAGE_CHANGE_PIN,
SYSCALL_STORAGE_ENSURE_NOT_WIPE_CODE,
SYSCALL_STORAGE_HAS_WIPE_CODE,
SYSCALL_STORAGE_CHANGE_WIPE_CODE,
SYSCALL_STORAGE_HAS,
SYSCALL_STORAGE_GET,
SYSCALL_STORAGE_SET,
SYSCALL_STORAGE_DELETE,
SYSCALL_STORAGE_SET_COUNTER,
SYSCALL_STORAGE_NEXT_COUNTER,
SYSCALL_ENTROPY_GET,
SYSCALL_TRANSLATIONS_WRITE,
@ -179,4 +169,28 @@ typedef enum {
SYSCALL_TROPIC_ECC_KEY_GENERATE,
SYSCALL_TROPIC_ECC_SIGN,
SYSCALL_STORAGE_GET,
// ------------------------------------------------------
// Following syscalls are executed in kernel thread mode
SYSCALL_STORAGE_INIT = SYSCALL_THREAD_MODE,
SYSCALL_STORAGE_WIPE,
SYSCALL_STORAGE_IS_UNLOCKED,
SYSCALL_STORAGE_LOCK,
SYSCALL_STORAGE_UNLOCK,
SYSCALL_STORAGE_HAS_PIN,
SYSCALL_STORAGE_PIN_FAILS_INCREASE,
SYSCALL_STORAGE_GET_PIN_REM,
SYSCALL_STORAGE_CHANGE_PIN,
SYSCALL_STORAGE_ENSURE_NOT_WIPE_CODE,
SYSCALL_STORAGE_HAS_WIPE_CODE,
SYSCALL_STORAGE_CHANGE_WIPE_CODE,
SYSCALL_STORAGE_HAS,
// SYSCALL_STORAGE_GET,
SYSCALL_STORAGE_SET,
SYSCALL_STORAGE_DELETE,
SYSCALL_STORAGE_SET_COUNTER,
SYSCALL_STORAGE_NEXT_COUNTER,
} syscall_number_t;

View File

@ -21,70 +21,10 @@
#include <sys/mpu.h>
#include "syscall_context.h"
#include "syscall_internal.h"
__attribute__((naked, no_stack_protector)) static uint32_t _invoke_app_callback(
uint32_t arg1, uint32_t arg2, uint32_t arg3, void *callback) {
__asm__ volatile(
"push {r1-r12, lr} \n"
#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
"mrs r12, PSPLIM \n" // Backup unprivileged stack limit
"push {r12} \n"
#endif
"mrs r12, PSP \n" // Backup unprivileged stack pointer
"push {r12} \n"
"sub r12, r12, #32 \n" // Reserve space for stack frame
"msr PSP, r12 \n"
"str r0, [r12, #0] \n" // pass r0
"str r1, [r12, #4] \n" // pass r1
"str r2, [r12, #8] \n" // pass r2
"mov r1, #0 \n"
"mov r4, r1 \n" // Clear registers r4-r11
"mov r5, r1 \n"
"mov r6, r1 \n"
"mov r7, r1 \n"
"mov r8, r1 \n"
"mov r9, r1 \n"
"mov r10, r1 \n"
"mov r11, r1 \n"
"str r1, [r12, #12] \n" // clear r3
"str r1, [r12, #16] \n" // clear r12
"str r1, [r12, #20] \n" // clear lr
"bic r3, r3, #1 \n"
"str r3, [r12, #24] \n" // return address
"ldr r1, = 0x01000000 \n"
"str r1, [r12, #28] \n" // xPSR
"vmov r0, s0 \n" // Use FPU instruction to ensure lazy
// stacking
#if !defined(__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE == 3U)
// return to Secure Thread mode (use Secure PSP)
"ldr lr, = 0xFFFFFFFD \n"
#else
// return to Thread mode (use PSP)
"ldr lr, = 0xFFFFFFBC \n"
#endif
"bx lr \n");
}
uint32_t invoke_app_callback(uint32_t args1, uint32_t arg2, uint32_t arg3,
void *callback) {
mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_APP);
uint32_t retval = _invoke_app_callback(args1, arg2, arg3, callback);
mpu_reconfig(mpu_mode);
return retval;
}
__attribute__((naked, no_stack_protector)) void return_from_app_callback(
__attribute__((naked, no_stack_protector)) void return_from_unpriv(
uint32_t retval, uint32_t *msp) {
__asm__ volatile(
"MSR MSP, R1 \n"

View File

@ -0,0 +1,30 @@
/*
* This file is part of the Trezor project, https://trezor.io/
*
* Copyright (c) SatoshiLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "syscall_context.h"
#ifdef KERNEL
applet_t* g_syscall_context;
void syscall_set_context(applet_t* applet) { g_syscall_context = applet; }
applet_t* syscall_get_context(void) { return g_syscall_context; }
#endif // KERNEL

View File

@ -0,0 +1,32 @@
/*
* This file is part of the Trezor project, https://trezor.io/
*
* Copyright (c) SatoshiLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <sys/applet.h>
#ifdef KERNEL
// Sets the context (applet) for all subsequent syscall processing
void syscall_set_context(applet_t* applet);
// Gets current syscall context (applet)
applet_t* syscall_get_context(void);
#endif // KERNEL

View File

@ -77,25 +77,34 @@
#include <io/touch.h>
#endif
#include "syscall_context.h"
#include "syscall_internal.h"
#include "syscall_verifiers.h"
bool g_in_app_callback = false;
static PIN_UI_WAIT_CALLBACK storage_init_callback = NULL;
static secbool storage_init_callback_wrapper(
uint32_t wait, uint32_t progress, enum storage_ui_message_t message) {
secbool result;
g_in_app_callback = true;
result = invoke_app_callback(wait, progress, message, storage_init_callback);
g_in_app_callback = false;
applet_t *applet = syscall_get_context();
result = systask_invoke_callback(&applet->task, wait, progress, message,
storage_init_callback);
return result;
}
__attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
uint32_t syscall) {
uint32_t syscall,
void *applet) {
syscall_set_context((applet_t *)applet);
switch (syscall) {
case SYSCALL_RETURN_FROM_CALLBACK: {
syscall_get_context()->task.in_callback = false;
systask_yield_to(systask_kernel());
break;
}
case SYSCALL_SYSTEM_EXIT: {
int exit_code = (int)args[0];
system_exit__verified(exit_code);
@ -148,7 +157,7 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
const sysevents_t *awaited = (sysevents_t *)args[0];
sysevents_t *signalled = (sysevents_t *)args[1];
uint32_t deadline = args[2];
if (!g_in_app_callback) {
if (!syscall_get_context()->task.in_callback) {
sysevents_poll__verified(awaited, signalled, deadline);
}
} break;

View File

@ -23,8 +23,7 @@
#include <sys/applet.h>
#include <sys/syscall.h>
#include "syscall_numbers.h"
#include <sys/syscall_numbers.h>
#ifndef KERNEL_MODE

View File

@ -0,0 +1,134 @@
/*
* This file is part of the Trezor project, https://trezor.io/
*
* Copyright (c) SatoshiLabs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef KERNEL
#include <trezor_rtl.h>
#include <sys/syscall.h>
#include <sys/syscall_ipc.h>
#include <sys/sysevent_source.h>
#include <sys/systask.h>
typedef struct {
// Task that requested the syscall
systask_t* task;
// Syscall number
syscall_number_t number;
// Syscall arguments
uint32_t args[6];
} syscall_struct_t;
typedef struct {
// Syscall to process
syscall_struct_t syscall;
} syscall_ipc_t;
static syscall_ipc_t g_syscall_ipc = {0};
// forward declaration
static const syshandle_vmt_t g_syscall_handle_vmt;
bool syscall_ipc_init(void) {
syscall_ipc_t* ipc = &g_syscall_ipc;
memset(ipc, 0, sizeof(*ipc));
if (!syshandle_register(SYSHANDLE_SYSCALL, &g_syscall_handle_vmt, ipc)) {
return false;
}
return true;
}
void syscall_ipc_enqueue(uint32_t* args, syscall_number_t number) {
syscall_ipc_t* ipc = &g_syscall_ipc;
// Enqueue the syscall
syscall_struct_t* syscall = &ipc->syscall;
syscall->task = systask_active();
syscall->number = number;
memcpy(syscall->args, args, sizeof(syscall->args));
// Switch to the kernel task to process the syscall
systask_yield_to(systask_kernel());
}
void syscall_ipc_dequeue(void) {
syscall_ipc_t* ipc = &g_syscall_ipc;
syscall_struct_t* syscall = &ipc->syscall;
if (syscall->task != NULL) {
// Process enqueued syscall
syscall_handler(syscall->args, syscall->number, syscall->task->applet);
// Copy return value back to the task's registers
systask_set_r0r1(syscall->task, syscall->args[0], syscall->args[1]);
// Remove the syscall from the queue
systask_t* task = syscall->task;
memset(syscall, 0, sizeof(*syscall));
// Get back to the unprivileged task
systask_yield_to(task);
}
}
static void on_task_killed(void* context, systask_id_t task_id) {
syscall_ipc_t* ipc = (syscall_ipc_t*)context;
if (ipc->syscall.task != NULL && ipc->syscall.task->id == task_id) {
memset(&ipc->syscall, 0, sizeof(ipc->syscall));
}
}
static inline bool syscall_requested(syscall_ipc_t* ipc) {
return (ipc->syscall.task != NULL);
}
static void on_event_poll(void* context, bool read_awaited,
bool write_awaited) {
syscall_ipc_t* ipc = (syscall_ipc_t*)context;
UNUSED(write_awaited);
if (read_awaited && syscall_requested(ipc)) {
syshandle_signal_read_ready(SYSHANDLE_SYSCALL, NULL);
}
}
static bool on_check_read_ready(void* context, systask_id_t task_id,
void* param) {
syscall_ipc_t* ipc = (syscall_ipc_t*)context;
UNUSED(param);
return (task_id == 0) && syscall_requested(ipc);
}
static const syshandle_vmt_t g_syscall_handle_vmt = {
.task_created = NULL,
.task_killed = on_task_killed,
.check_read_ready = on_check_read_ready,
.check_write_ready = NULL,
.poll = on_event_poll,
};
#endif // KERNEL

View File

@ -22,6 +22,7 @@
#pragma GCC optimize("no-stack-protector")
#include <trezor_model.h>
#include <trezor_rtl.h>
#include <sys/applet.h>
@ -36,7 +37,7 @@ static inline bool inside_area(const void *addr, size_t len,
}
bool probe_read_access(const void *addr, size_t len) {
applet_t *applet = applet_active();
applet_t *applet = syscall_get_context();
if (applet == NULL) {
return false;
@ -86,7 +87,7 @@ bool probe_read_access(const void *addr, size_t len) {
}
bool probe_write_access(void *addr, size_t len) {
applet_t *applet = applet_active();
applet_t *applet = syscall_get_context();
if (applet == NULL) {
return false;
@ -118,4 +119,11 @@ bool probe_write_access(void *addr, size_t len) {
return false;
}
void handle_access_violation(const char *file, int line) {
static const char *msg = "Access violation";
applet_t *applet = syscall_get_context();
systask_t *task = applet != NULL ? &applet->task : systask_active();
systask_exit_fatal(task, msg, strlen(msg), file, strlen(file), line);
}
#endif // KERNEL

View File

@ -21,8 +21,11 @@
#include <trezor_types.h>
#include <sys/applet.h>
#include <sys/system.h>
#include "syscall_context.h"
#ifdef KERNEL
// Checks if the current application task has read access to the
@ -33,11 +36,15 @@ bool probe_read_access(const void *addr, size_t len);
// given memory range.
bool probe_write_access(void *addr, size_t len);
// Handles access violation by exiting the current application task
// with a fatal error and the message "Access violation".
void handle_access_violation(const char *file, int line);
// Exits the current application task with an fatal error
// with the message "Access violation".
#define apptask_access_violation() \
do { \
system_exit_fatal("Access violation", __FILE__, __LINE__); \
#define apptask_access_violation() \
do { \
handle_access_violation(__FILE__, __LINE__); \
} while (0)
#endif // KERNEL

View File

@ -495,7 +495,7 @@ static PIN_UI_WAIT_CALLBACK storage_init_callback = NULL;
static void storage_init_callback_wrapper(uint32_t wait, uint32_t progress,
enum storage_ui_message_t message) {
secbool retval = storage_init_callback(wait, progress, message);
syscall_return_from_callback(retval);
syscall_invoke1(retval, SYSCALL_RETURN_FROM_CALLBACK);
}
void storage_init(PIN_UI_WAIT_CALLBACK callback, const uint8_t *salt,

View File

@ -32,6 +32,7 @@ typedef enum {
SYSHANDLE_TOUCH,
SYSHANDLE_USB,
SYSHANDLE_BLE,
SYSHANDLE_SYSCALL,
SYSHANDLE_COUNT,
} syshandle_t;

View File

@ -131,6 +131,9 @@ typedef struct {
// Applet bound to the task
void* applet;
// Set if the task is processing the kernel callback
bool in_callback;
} systask_t;
// Initializes the scheduler for tasks
@ -173,6 +176,17 @@ 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);
// Invokes the callback function in the context of the given task
// uint32_t callback(uint32_t arg1, uint32_t arg2, uint32_t arg3);
uint32_t systask_invoke_callback(systask_t* task, uint32_t arg1, uint32_t arg2,
uint32_t arg3, void* callback);
// Sets R0 and R1 registers of the suspended task
void systask_set_r0r1(systask_t* task, uint32_t r0, uint32_t r1);
// Gets R0 register value of the suspended task
uint32_t systask_get_r0(systask_t* task);
// Gets the ID (zero-based index up SYSTASK_MAX_TASKS - 1) of the given task.
systask_id_t systask_id(const systask_t* task);

View File

@ -28,6 +28,7 @@
#include <sys/linker_utils.h>
#include <sys/mpu.h>
#include <sys/syscall.h>
#include <sys/syscall_ipc.h>
#include <sys/sysevent_source.h>
#include <sys/systask.h>
#include <sys/system.h>
@ -245,6 +246,62 @@ cleanup:
return false;
}
uint32_t systask_invoke_callback(systask_t* task, uint32_t arg1, uint32_t arg2,
uint32_t arg3, void* callback) {
uint32_t original_sp = task->sp;
if (!systask_push_call(task, callback, arg1, arg2, arg3)) {
// There is not enough space on the unprivileged stack
error_shutdown("Callback stack low");
}
// This flag signals that the task is currently executing a callback.
// Is reset by proper return from the callback via
// return_from_unprivileged_callback() function.
task->in_callback = true;
systask_yield_to(task);
if (task->killed) {
// Task was killed while executing the callback
error_shutdown("Callback crashed");
}
if (task->in_callback) {
// Unprivileged stack pointer contains unexpected value.
// This is likely a sign of a unexpected task switch during the
// callback execution (e.g. by a system call).
error_shutdown("Callback invalid op");
}
uint32_t retval = systask_get_r0(task);
task->sp = original_sp;
return retval;
}
void systask_set_r0r1(systask_t* task, uint32_t r0, uint32_t r1) {
uint32_t* stack = (uint32_t*)task->sp;
if ((task->exc_return & 0x10) == 0) {
stack += 16; // Skip the FP context S16-S32
stack += 8; // Skip R4-R11
}
stack[STK_FRAME_R0] = r0;
stack[STK_FRAME_R1] = r1;
}
uint32_t systask_get_r0(systask_t* task) {
uint32_t* stack = (uint32_t*)task->sp;
if ((task->exc_return & 0x10) == 0) {
stack += 16; // Skip the FP context S16-S32
stack += 8; // Skip R4-R11
}
return stack[STK_FRAME_R0];
}
static void systask_kill(systask_t* task) {
systask_scheduler_t* scheduler = &g_systask_scheduler;
@ -554,15 +611,17 @@ __attribute__((no_stack_protector, used)) static uint32_t svc_handler(
break;
#ifdef KERNEL
case SVC_SYSCALL:
syscall_handler(args, r6);
stack[0] = args[0];
stack[1] = args[1];
if ((r6 & SYSCALL_THREAD_MODE) != 0) {
syscall_ipc_enqueue(args, r6);
} else {
syscall_handler(args, r6, systask_active()->applet);
stack[0] = args[0];
stack[1] = args[1];
}
break;
case SVC_CALLBACK_RETURN:
// g_return_value = args[0]
// exc_return = return_from_callback;
mpu_restore(mpu_mode);
return_from_app_callback(args[0], msp);
return_from_unpriv(args[0], msp);
break;
#endif
default:

View File

@ -25,6 +25,7 @@
#include <sys/linker_utils.h>
#include <sys/mpu.h>
#include <sys/stack_utils.h>
#include <sys/syscall_ipc.h>
#include <sys/systask.h>
#include <sys/system.h>
#include <sys/systick.h>
@ -55,6 +56,9 @@ void system_init(systask_error_handler_t error_handler) {
systask_scheduler_init(error_handler);
systick_init();
systimer_init();
#ifdef KERNEL
syscall_ipc_init();
#endif
}
void system_deinit(void) {

View File

@ -81,7 +81,9 @@ def stm32f4_common_files(env, defines, sources, paths):
"embed/sys/startup/stm32f4/startup_init.c",
"embed/sys/startup/stm32f4/vectortable.S",
"embed/sys/syscall/stm32/syscall.c",
"embed/sys/syscall/stm32/syscall_context.c",
"embed/sys/syscall/stm32/syscall_dispatch.c",
"embed/sys/syscall/stm32/syscall_ipc.c",
"embed/sys/syscall/stm32/syscall_probe.c",
"embed/sys/syscall/stm32/syscall_stubs.c",
"embed/sys/syscall/stm32/syscall_verifiers.c",

View File

@ -100,7 +100,9 @@ def stm32u5_common_files(env, features_wanted, defines, sources, paths):
"embed/sys/startup/stm32u5/startup_init.c",
"embed/sys/startup/stm32u5/vectortable.S",
"embed/sys/syscall/stm32/syscall.c",
"embed/sys/syscall/stm32/syscall_context.c",
"embed/sys/syscall/stm32/syscall_dispatch.c",
"embed/sys/syscall/stm32/syscall_ipc.c",
"embed/sys/syscall/stm32/syscall_probe.c",
"embed/sys/syscall/stm32/syscall_stubs.c",
"embed/sys/syscall/stm32/syscall_verifiers.c",