1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-27 07:21:18 +01:00

cpu/native: unify ucontext manipulation

This commit is contained in:
carl 2025-03-07 14:36:28 +01:00
parent 64283b52aa
commit b5eff6a107
5 changed files with 131 additions and 63 deletions

View File

@ -237,7 +237,29 @@ extern ucontext_t *_native_isr_context;
*/
extern void _native_isr_leave(void);
/**
* @brief Makes ISR context so that execution continues at `func` when the context is applied
*
* @param func Function executed when `_native_isr_context` is applied
*/
static inline void _native_isr_context_make(void (*func)(void)) {
_native_isr_context->uc_stack.ss_sp = _isr_stack;
_native_isr_context->uc_stack.ss_size = sizeof(_isr_stack);
_native_isr_context->uc_stack.ss_flags = 0;
/* Create the ISR context, will execute _isr_schedule_and_switch */
makecontext(_native_isr_context, func, 0);
}
/**
* @brief Retrieves user context
* @returns `ucontext_t`
*/
static inline ucontext_t* _native_user_context(void) {
/* Use intermediate cast to uintptr_t to silence -Wcast-align.
* stacks are manually word aligned in thread_static_init() */
return (ucontext_t *)(uintptr_t)thread_get_active()->sp;
}
/** @} */
/* MARK: - Native Process State */

View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2013 - 2016 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
* Copyright (C) 2025 carl-tud
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#ifndef UTIL_UCONTEXT_H
#define UTIL_UCONTEXT_H
#if USE_LIBUCONTEXT
# include <libucontext/libucontext.h>
#else
# include <ucontext.h>
#endif /* USE_LIBUCONTEXT */
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup cpu_native
* @{
*/
/* MARK: - Context accessors */
/**
* @name Context accessors
* @{
*/
/**
* @brief Retrieves function pointer generated during calls to `makecontext`/`setcontext`/`swapcontext`
* @param context `ucontext_t`
* @returns Function pointer (does not need to be start of a function, points to instruction)
*/
static inline uintptr_t _context_get_fptr(ucontext_t *context) {
# if defined(__FreeBSD__) /* FreeBSD */
return (uintptr_t)((struct sigcontext *)context)->sc_eip;
# elif defined(__linux__) /* Linux */
# if defined(__arm__)
return (uintptr_t)((ucontext_t *)context)->uc_mcontext.arm_pc;
# elif defined(__x86_64__)
return (uintptr_t)((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP];
# elif defined(__i386__)
return (uintptr_t)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP];
# else
# error "Unsupported Linux architecture"
# endif
# else
# error "Operating system unsupported"
# endif
}
/**
* @brief Retrieves function pointer generated during calls to `makecontext`/`setcontext`/`swapcontext`
* @param context `ucontext_t`
* @param func Function pointer
*/
static inline void _context_set_fptr(ucontext_t *context, uintptr_t func) {
# if defined(__FreeBSD__) /* FreeBSD */
((struct sigcontext *)context)->sc_eip = (unsigned int)func;
# elif defined(__linux__) /* Linux */
# if defined(__arm__)
((ucontext_t *)context)->uc_mcontext.arm_lr = func;
((ucontext_t *)context)->uc_mcontext.arm_pc = func;
# elif defined(__x86_64__)
((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP] = (greg_t)func;
# elif defined(__i386__)
((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP] = func;
# else
# error "Unsupported Linux architecture"
# endif
# else
# error "Operating system unsupported"
# endif
}
/** @} */
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* UTIL_UCONTEXT_H */

View File

@ -323,36 +323,22 @@ void native_signal_action(int sig, siginfo_t *info, void *context)
return;
}
native_isr_context.uc_stack.ss_sp = __isr_stack;
native_isr_context.uc_stack.ss_size = sizeof(__isr_stack);
native_isr_context.uc_stack.ss_flags = 0;
makecontext(&native_isr_context, native_irq_handler, 0);
/* Use intermediate cast to uintptr_t to silence -Wcast-align.
* stacks are manually word aligned in thread_stack_init() */
_native_cur_ctx = (ucontext_t *)(uintptr_t)thread_get_active()->sp;
/* We will switch to the ISR context with ISR stack */
_native_isr_context_make(_native_call_sig_handlers_and_switch);
/* Current user thread context */
_native_current_context = _native_user_context();
DEBUG_IRQ("\n\n\t\tnative_signal_action: return to _native_sig_leave_tramp\n\n");
/* disable interrupts in context */
isr_set_sigmask((ucontext_t *)context);
_set_sigmask((ucontext_t *)context);
_native_in_isr = 1;
#if defined(__FreeBSD__)
_native_saved_eip = ((struct sigcontext *)context)->sc_eip;
((struct sigcontext *)context)->sc_eip = (unsigned int)&_native_sig_leave_tramp;
#else /* Linux */
#if defined(__arm__)
_native_saved_eip = ((ucontext_t *)context)->uc_mcontext.arm_pc;
((ucontext_t *)context)->uc_mcontext.arm_pc = (unsigned int)&_native_sig_leave_tramp;
#else /* Linux/x86 */
#ifdef __x86_64__
_native_saved_eip = ((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP];
((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP] = (uintptr_t)&_native_sig_leave_tramp;
#else
//printf("\n\033[31mEIP:\t%p\ngo switching\n\n\033[0m", (void*)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP]);
_native_saved_eip = ((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP];
((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP] = (unsigned int)&_native_sig_leave_tramp;
#endif
#endif
#endif
/* Get PC/LR. This is where we will resume execution on the userspace thread. */
_native_user_fptr = (uintptr_t)_context_get_fptr((ucontext_t *)context);
/* Now we want to go to _native_sig_leave_tramp before resuming execution at _native_user_fptr. */
_context_set_fptr(context, (uintptr_t)_native_sig_leave_tramp);
}
static void _set_signal_handler(int sig, bool add)
@ -487,10 +473,7 @@ void native_interrupt_init(void)
err(EXIT_FAILURE, "native_interrupt_init: getcontext");
}
native_isr_context.uc_stack.ss_sp = __isr_stack;
native_isr_context.uc_stack.ss_size = sizeof(__isr_stack);
native_isr_context.uc_stack.ss_flags = 0;
_native_isr_ctx = &native_isr_context;
_native_isr_context_make(_native_call_sig_handlers_and_switch);
static stack_t sigstk;
sigstk.ss_sp = malloc(SIGSTKSZ);

View File

@ -55,30 +55,6 @@ extern netdev_tap_t netdev_tap;
static ucontext_t _end_context;
/**
* make the new context assign `_native_in_isr = 0` before resuming
*/
static void _native_mod_ctx_leave_sigh(ucontext_t *ctx)
{
#if defined(__FreeBSD__)
_native_saved_eip = ((struct sigcontext *)ctx)->sc_eip;
((struct sigcontext *)ctx)->sc_eip = (unsigned int)&_native_sig_leave_handler;
#else /* Linux */
#if defined(__arm__)
_native_saved_eip = ((ucontext_t *)ctx)->uc_mcontext.arm_pc;
((ucontext_t *)ctx)->uc_mcontext.arm_pc = (unsigned int)&_native_sig_leave_handler;
#else /* Linux/x86 */
#ifdef __x86_64__
_native_saved_eip = ctx->uc_mcontext.gregs[REG_RIP];
ctx->uc_mcontext.gregs[REG_RIP] = (unsigned long)&_native_sig_leave_handler;
#else
_native_saved_eip = ctx->uc_mcontext.gregs[REG_EIP];
ctx->uc_mcontext.gregs[REG_EIP] = (unsigned int)&_native_sig_leave_handler;
#endif
#endif
#endif
}
/**
* TODO: implement
*/

View File

@ -39,6 +39,7 @@
# include "time_units.h"
# include "ztimer64.h"
#endif
#include "stdio_base.h"
#include "kernel_defines.h"
@ -80,15 +81,10 @@ void _native_syscall_leave(void)
)
{
_native_in_isr = 1;
/* Use intermediate cast to uintptr_t to silence -Wcast-align.
* stacks are manually word aligned in thread_static_init() */
_native_cur_ctx = (ucontext_t *)(uintptr_t)thread_get_active()->sp;
native_isr_context.uc_stack.ss_sp = __isr_stack;
native_isr_context.uc_stack.ss_size = __isr_stack_size;
native_isr_context.uc_stack.ss_flags = 0;
native_interrupts_enabled = 0;
makecontext(&native_isr_context, native_irq_handler, 0);
if (swapcontext(_native_cur_ctx, &native_isr_context) == -1) {
_native_interrupts_enabled = false;
_native_isr_context_make(_native_call_sig_handlers_and_switch);
if (swapcontext(_native_user_context(), _native_isr_context) == -1) {
err(EXIT_FAILURE, "_native_syscall_leave: swapcontext");
}
}