mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-02 07:28:21 +00:00
signal: ucontext and a fix
This commit is contained in:
@@ -161,7 +161,7 @@ void signal_signalthread(struct thread_t *thread, int signal, bool urgent);
|
|||||||
void signal_pending(struct thread_t *, sigset_t *sigset);
|
void signal_pending(struct thread_t *, sigset_t *sigset);
|
||||||
void signal_suspend(sigset_t *sigset);
|
void signal_suspend(sigset_t *sigset);
|
||||||
int signal_wait(sigset_t *sigset, timespec_t *timeout, siginfo_t *siginfo, int *signum);
|
int signal_wait(sigset_t *sigset, timespec_t *timeout, siginfo_t *siginfo, int *signum);
|
||||||
bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uint64_t syscallret, uint64_t syscallerrno);
|
bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uint64_t syscallret, uint64_t syscallerrno, bool *need_context_switch);
|
||||||
extern int signal_defaultactions[NSIG];
|
extern int signal_defaultactions[NSIG];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,13 +9,89 @@
|
|||||||
|
|
||||||
#define ARCH_SIGNAL_GETFROMRETURN(x)
|
#define ARCH_SIGNAL_GETFROMRETURN(x)
|
||||||
|
|
||||||
|
#define MCONTEXT_REG_R8 0
|
||||||
|
#define MCONTEXT_REG_R9 1
|
||||||
|
#define MCONTEXT_REG_R10 2
|
||||||
|
#define MCONTEXT_REG_R11 3
|
||||||
|
#define MCONTEXT_REG_R12 4
|
||||||
|
#define MCONTEXT_REG_R13 5
|
||||||
|
#define MCONTEXT_REG_R14 6
|
||||||
|
#define MCONTEXT_REG_R15 7
|
||||||
|
#define MCONTEXT_REG_RDI 8
|
||||||
|
#define MCONTEXT_REG_RSI 9
|
||||||
|
#define MCONTEXT_REG_RBP 10
|
||||||
|
#define MCONTEXT_REG_RBX 11
|
||||||
|
#define MCONTEXT_REG_RDX 12
|
||||||
|
#define MCONTEXT_REG_RAX 13
|
||||||
|
#define MCONTEXT_REG_RCX 14
|
||||||
|
#define MCONTEXT_REG_RSP 15
|
||||||
|
#define MCONTEXT_REG_RIP 16
|
||||||
|
#define MCONTEXT_REG_EFL 17
|
||||||
|
#define MCONTEXT_REG_CSGSFS 18
|
||||||
|
#define MCONTEXT_REG_ERR 19
|
||||||
|
#define MCONTEXT_REG_TRAPNO 20
|
||||||
|
#define MCONTEXT_REG_OLDMASK 21
|
||||||
|
#define MCONTEXT_REG_CR2 22
|
||||||
|
#define MCONTEXT_NGREG 23
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *restorer;
|
unsigned long gregs[MCONTEXT_NGREG];
|
||||||
|
uint8_t fpu_state[512];
|
||||||
|
unsigned long __reserved1[8];
|
||||||
|
} mcontext_t;
|
||||||
|
|
||||||
|
// this structure should have a part of it matching the ucontext from the abi
|
||||||
|
// which then gets its address returned by the ARCH_SIGFRAME_GET_UCONTEXT_POINTER macro
|
||||||
|
typedef struct {
|
||||||
|
void *restorer; // for return from signal
|
||||||
|
|
||||||
|
// ucontext starts here
|
||||||
|
unsigned long uc_flags; // can be zero
|
||||||
|
void *uc_link; // unused for signals
|
||||||
stack_t oldstack;
|
stack_t oldstack;
|
||||||
|
mcontext_t mcontext;
|
||||||
sigset_t oldmask;
|
sigset_t oldmask;
|
||||||
|
|
||||||
|
// astral bits
|
||||||
context_t context;
|
context_t context;
|
||||||
extracontext_t extracontext;
|
extracontext_t extracontext;
|
||||||
siginfo_t siginfo;
|
siginfo_t siginfo;
|
||||||
} sigframe_t;
|
} sigframe_t;
|
||||||
|
|
||||||
|
#define ARCH_SIGFRAME_GET_UCONTEXT_POINTER(x) (&(x)->uc_flags)
|
||||||
|
|
||||||
|
static inline void arch_sigframe_prepare_mcontext(sigframe_t *sigframe) {
|
||||||
|
context_t *context = &sigframe->context;
|
||||||
|
extracontext_t *extracontext = &sigframe->extracontext;
|
||||||
|
unsigned long *gregs = sigframe->mcontext.gregs;
|
||||||
|
uint8_t *fpu_state = sigframe->mcontext.fpu_state;
|
||||||
|
|
||||||
|
gregs[MCONTEXT_REG_R8] = context->r8;
|
||||||
|
gregs[MCONTEXT_REG_R9] = context->r9;
|
||||||
|
gregs[MCONTEXT_REG_R10] = context->r10;
|
||||||
|
gregs[MCONTEXT_REG_R11] = context->r11;
|
||||||
|
gregs[MCONTEXT_REG_R12] = context->r12;
|
||||||
|
gregs[MCONTEXT_REG_R13] = context->r13;
|
||||||
|
gregs[MCONTEXT_REG_R14] = context->r14;
|
||||||
|
gregs[MCONTEXT_REG_R15] = context->r15;
|
||||||
|
gregs[MCONTEXT_REG_RDI] = context->rdi;
|
||||||
|
gregs[MCONTEXT_REG_RSI] = context->rsi;
|
||||||
|
gregs[MCONTEXT_REG_RBP] = context->rbp;
|
||||||
|
gregs[MCONTEXT_REG_RBX] = context->rbx;
|
||||||
|
gregs[MCONTEXT_REG_RDX] = context->rdx;
|
||||||
|
gregs[MCONTEXT_REG_RAX] = context->rax;
|
||||||
|
gregs[MCONTEXT_REG_RCX] = context->rcx;
|
||||||
|
gregs[MCONTEXT_REG_RSP] = context->rsp;
|
||||||
|
gregs[MCONTEXT_REG_RIP] = context->rip;
|
||||||
|
gregs[MCONTEXT_REG_EFL] = context->rflags;
|
||||||
|
gregs[MCONTEXT_REG_CSGSFS] = 0;
|
||||||
|
gregs[MCONTEXT_REG_ERR] = context->error;
|
||||||
|
gregs[MCONTEXT_REG_TRAPNO] = 0;
|
||||||
|
gregs[MCONTEXT_REG_OLDMASK] = 0;
|
||||||
|
gregs[MCONTEXT_REG_CR2] = context->cr2;
|
||||||
|
|
||||||
|
memcpy(fpu_state, extracontext->fx, 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ typedef struct {
|
|||||||
} checkargs_t;
|
} checkargs_t;
|
||||||
|
|
||||||
// SHOULD NOT BE CALLED WITH THE SCHEDULER STACK
|
// SHOULD NOT BE CALLED WITH THE SCHEDULER STACK
|
||||||
static void userspacecheck(void *_args) {
|
static bool userspacecheck(void *_args) {
|
||||||
checkargs_t *args = _args;
|
checkargs_t *args = _args;
|
||||||
thread_t *thread = current_thread();
|
thread_t *thread = current_thread();
|
||||||
|
|
||||||
@@ -171,7 +171,10 @@ static void userspacecheck(void *_args) {
|
|||||||
sched_threadexit();
|
sched_threadexit();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (signal_check(thread, args->context, args->syscall, args->syscallret, args->syscallerrno)) ;
|
bool need_context_switch = false;
|
||||||
|
|
||||||
|
while (signal_check(thread, args->context, args->syscall, args->syscallret, args->syscallerrno, &need_context_switch)) ;
|
||||||
|
return need_context_switch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checktrampoline(context_t *context, void *_args) {
|
static void checktrampoline(context_t *context, void *_args) {
|
||||||
@@ -203,7 +206,10 @@ __attribute__((no_caller_saved_registers)) void sched_userspacecheck(context_t *
|
|||||||
if (&args < (checkargs_t *)current_cpu()->schedulerstack && &args >= (checkargs_t *)((uintptr_t)current_cpu()->schedulerstack - SCHEDULER_STACK_SIZE)) {
|
if (&args < (checkargs_t *)current_cpu()->schedulerstack && &args >= (checkargs_t *)((uintptr_t)current_cpu()->schedulerstack - SCHEDULER_STACK_SIZE)) {
|
||||||
arch_context_saveandcall(checktrampoline, current_thread()->kernelstacktop, &args);
|
arch_context_saveandcall(checktrampoline, current_thread()->kernelstacktop, &args);
|
||||||
} else {
|
} else {
|
||||||
userspacecheck(&args);
|
if (userspacecheck(&args)) {
|
||||||
|
// need context switch
|
||||||
|
arch_context_switch(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current_cpu()->intstatus = intstatus;
|
current_cpu()->intstatus = intstatus;
|
||||||
|
|||||||
@@ -423,7 +423,7 @@ void signal_signalproc(struct proc_t *proc, int signal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true if should retry check
|
// returns true if should retry check
|
||||||
bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uint64_t syscallret, uint64_t syscallerrno) {
|
bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uint64_t syscallret, uint64_t syscallerrno, bool *need_context_switch) {
|
||||||
bool retry = false;
|
bool retry = false;
|
||||||
proc_t *proc = thread->proc;
|
proc_t *proc = thread->proc;
|
||||||
|
|
||||||
@@ -563,6 +563,7 @@ bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uin
|
|||||||
}
|
}
|
||||||
memcpy(&sigframe.context, context, sizeof(context_t));
|
memcpy(&sigframe.context, context, sizeof(context_t));
|
||||||
memcpy(&sigframe.extracontext, &thread->extracontext, sizeof(extracontext_t));
|
memcpy(&sigframe.extracontext, &thread->extracontext, sizeof(extracontext_t));
|
||||||
|
arch_sigframe_prepare_mcontext(&sigframe);
|
||||||
// TODO siginfo
|
// TODO siginfo
|
||||||
|
|
||||||
if (usercopy_touser(stack, &sigframe, sizeof(sigframe_t))) {
|
if (usercopy_touser(stack, &sigframe, sizeof(sigframe_t))) {
|
||||||
@@ -591,11 +592,13 @@ bool signal_check(struct thread_t *thread, context_t *context, bool syscall, uin
|
|||||||
CTX_SP(context) = (uint64_t)stack;
|
CTX_SP(context) = (uint64_t)stack;
|
||||||
CTX_ARG0(context) = signal;
|
CTX_ARG0(context) = signal;
|
||||||
CTX_ARG1(context) = 0; // TODO pass siginfo
|
CTX_ARG1(context) = 0; // TODO pass siginfo
|
||||||
CTX_ARG2(context) = 0; // TODO ucontext
|
CTX_ARG2(context) = (uint64_t)ARCH_SIGFRAME_GET_UCONTEXT_POINTER((sigframe_t*)stack);
|
||||||
|
|
||||||
// reset handler if asked for
|
// reset handler if asked for
|
||||||
if (action->flags & SA_RESETHAND)
|
if (action->flags & SA_RESETHAND)
|
||||||
memset(action, 0, sizeof(sigaction_t));
|
memset(action, 0, sizeof(sigaction_t));
|
||||||
|
|
||||||
|
*need_context_switch = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
|||||||
Reference in New Issue
Block a user