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:
parent
64283b52aa
commit
b5eff6a107
@ -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 */
|
||||
|
||||
91
cpu/native/include/util/ucontext.h
Normal file
91
cpu/native/include/util/ucontext.h
Normal 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 */
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user