On Fri, Apr 15, 2011 at 3:33 PM, Gilles Chanteperdrix
<[email protected]> wrote:
> Henri Roosen wrote:
>> Ok, I'm back on this one now.
>>
>> I couldn't find the 'the signal rebase over the mayday support'
>> patches which Philippe mentioned. I searched the xenomai-2.5 and
>> xenomai-head trees. Is it somewhere available? It might be a good
>> starting point.
>
> When Philippe said: "So you need the signal rebase over the mayday
> support I merged a few months ago.". The "I merged a few months ago" was
> referring to the mayday support, not the signal rebase. This signal
> rebase does not exist. Because, especially due to FPU handling, it is
> not a trivial thing to do. sigcontext makes things even more complicated.
>
>>
>> The way I see it, currently available is an implementation like used
>> in sigtest. This means using a special skin that gets a handler
>> installed for signals at xeno_bind_skin(..., handler). Current status
>> seems to me a framework for supporting kill system calls. As far as I
>> can see the signal reporting part has no support for sigcontext (which
>> is a requirement for us). Also there is no connection of events like
>> SIGFPE to this mechanism.
>
> The current framework allows:
> - sending a signal to a thread
> - getting the handler executed by the thread.
>
> But, nothing sends signals to a thread, and nothings allows registering
> handlers for handling different signals.
>
> What the mayday support would changes is the way a signal handler could
> get executed by a thread.
>
>>
>> Where I see the mayday implementation comes in use is when sending
>> signals to other threads: it forces the target thread to make a kernel
>> call from userspace. Then the handle_rt_signals() function can handle
>> the pending signals.
>> Is the mayday implementation also needed for exception signals
>> (SIGFPE), which are generated by the task itself? I see the current
>> implementation needs a system call from userspace to provide the
>> struct xnsigs to kernel space. So I guess answer to the last question
>> is yes... but that might also have some overhead as we were in kernel
>> space already..
>
> No real overhead. Since we are in kernel-space, the signal handler will
> get executed when going back to user-space. The exception causes a
> switch to kernel-space anyway.
>
>>
>> Is it a good idea to implement SIGFPE support using the signal-skin?
>
> I think it is a better idea to implement this with whatever skin you are
> using native, posix, etc...
>
I did some tests with the RT-signal handling currently available in
Xenomai w.r.t. exception handling, but unfortunately didn't lead to
any solution. Then I decided base it more on the native Linux
exception handling.
I've made an experimental implementation for the native skin x86-32
exception handling in primary domain. I used the 2.6.32.20 kernel and
did some basic tests with divide by zero. Because we need the
exception context the patch unfortunately contains a lot of arch
specific code.
Please find the patch attached to this email for anyone who wants to
experiment with this. Let me know of any comments and findings.
Thanks,
Henri.
>>
>> So for me there are some unclarities of how to implement primary
>> domain exception handling from userspace. Would be good when this
>> email triggers a discussion of how to correctly implement it so I can
>> then make a useful contribution to the project.
>>
>> Thanks,
>> Henri.
>>
>
>
> --
> Gilles.
>
diff --git a/include/asm-arm/bits/shadow.h b/include/asm-arm/bits/shadow.h
index 270156e..b2056dd 100644
--- a/include/asm-arm/bits/shadow.h
+++ b/include/asm-arm/bits/shadow.h
@@ -291,6 +291,23 @@ static inline void xnarch_fixup_mayday(struct xnarchtcb *tcb,
#endif
}
+static inline int xnshadow_setup_trap_info(unsigned int vector,
+ struct pt_regs *regs, long errcode, int *sig, siginfo_t *info)
+{
+ return -ENOSYS;
+}
+
+static inline int xnshadow_setup_rt_frame(int sig, void *handler, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs, void __user *restorer)
+{
+ return -ENOSYS;
+}
+
+static inline long xnshadow_rt_sigreturn(struct pt_regs *regs)
+{
+ return -ENOSYS;
+}
+
#endif /* XNARCH_HAVE_MAYDAY */
#endif /* !_XENO_ASM_ARM_BITS_SHADOW_H */
diff --git a/include/asm-blackfin/bits/shadow.h b/include/asm-blackfin/bits/shadow.h
index 778cf30..aead1b2 100644
--- a/include/asm-blackfin/bits/shadow.h
+++ b/include/asm-blackfin/bits/shadow.h
@@ -142,6 +142,23 @@ static inline void xnarch_fixup_mayday(struct xnarchtcb *tcb,
regs->r5 = tcb->mayday.r5;
}
+static inline int xnshadow_setup_trap_info(unsigned int vector,
+ struct pt_regs *regs, long errcode, int *sig, siginfo_t *info)
+{
+ return -ENOSYS;
+}
+
+static inline int xnshadow_setup_rt_frame(int sig, void *handler, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs, void __user *restorer)
+{
+ return -ENOSYS;
+}
+
+static inline long xnshadow_rt_sigreturn(struct pt_regs *regs)
+{
+ return -ENOSYS;
+}
+
#endif /* XNARCH_HAVE_MAYDAY */
#endif /* !_XENO_ASM_BLACKFIN_BITS_SHADOW_H */
diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h
index 7e3d01a..d4ae122 100644
--- a/include/asm-generic/syscall.h
+++ b/include/asm-generic/syscall.h
@@ -48,6 +48,7 @@
#define __xn_sys_get_next_sigs 10 /* only unqueue pending signals. */
#define __xn_sys_drop_u_mode 11 /* stop updating thread->u_mode */
#define __xn_sys_mayday 12 /* request mayday fixup */
+#define __xn_sys_rt_sig_return 13 /* request signal return fixup */
#define XENOMAI_LINUX_DOMAIN 0
#define XENOMAI_XENO_DOMAIN 1
diff --git a/include/asm-powerpc/bits/shadow.h b/include/asm-powerpc/bits/shadow.h
index 319f48d..57aa30f 100644
--- a/include/asm-powerpc/bits/shadow.h
+++ b/include/asm-powerpc/bits/shadow.h
@@ -118,6 +118,23 @@ static inline void xnarch_fixup_mayday(struct xnarchtcb *tcb,
regs->gpr[8] = tcb->mayday.r8;
}
+static inline int xnshadow_setup_trap_info(unsigned int vector,
+ struct pt_regs *regs, long errcode, int *sig, siginfo_t *info)
+{
+ return -ENOSYS;
+}
+
+static inline int xnshadow_setup_rt_frame(int sig, void *handler, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs, void __user *restorer)
+{
+ return -ENOSYS;
+}
+
+static inline long xnshadow_rt_sigreturn(struct pt_regs *regs)
+{
+ return -ENOSYS;
+}
+
#endif /* XNARCH_HAVE_MAYDAY */
#endif /* !_XENO_ASM_POWERPC_BITS_SHADOW_H */
diff --git a/include/asm-x86/bits/shadow_32.h b/include/asm-x86/bits/shadow_32.h
index 41080b1..0717b26 100644
--- a/include/asm-x86/bits/shadow_32.h
+++ b/include/asm-x86/bits/shadow_32.h
@@ -51,6 +51,8 @@ static void xnarch_schedule_tail(struct task_struct *prev)
#ifdef XNARCH_HAVE_MAYDAY
+#include <asm/sigframe.h>
+
static inline void xnarch_setup_mayday_page(void *page)
{
/*
@@ -71,7 +73,7 @@ static inline void xnarch_setup_mayday_page(void *page)
* Also note that if SEP is present, we always assume NPTL on
* the user side.
*/
- static const struct {
+ static struct {
struct __attribute__ ((__packed__)) {
u8 op;
u32 imm;
@@ -103,7 +105,7 @@ static inline void xnarch_setup_mayday_page(void *page)
.bug = 0x0b0f,
};
- static const struct {
+ static struct {
struct __attribute__ ((__packed__)) {
u8 op;
u32 imm;
@@ -127,10 +129,19 @@ static inline void xnarch_setup_mayday_page(void *page)
.bug = 0x0b0f,
};
- if (cpu_has_sep)
+ if (cpu_has_sep) {
memcpy(page, &code_sep, sizeof(code_sep));
- else
+ code_sep.mov_eax.imm =
+ __xn_mux_code(0, __xn_sys_rt_sig_return);
+ memcpy((char *)page + XNSHADOW_MD_SIGRETURN_OFFS, &code_sep,
+ sizeof(code_sep));
+ } else {
memcpy(page, &code_nosep, sizeof(code_nosep));
+ code_nosep.mov_eax.imm =
+ __xn_mux_code(0, __xn_sys_rt_sig_return);
+ memcpy((char *)page + XNSHADOW_MD_SIGRETURN_OFFS, &code_nosep,
+ sizeof(code_nosep));
+ }
/* no cache flush required. */
}
@@ -158,6 +169,320 @@ static inline void xnarch_fixup_mayday(struct xnarchtcb *tcb,
regs->x86reg_bp = tcb->mayday.ebp;
}
+/*
+ * Non-blocking signal stack functions based on linux-2.6.32.20
+ */
+#define __FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
+ X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
+ X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
+ X86_EFLAGS_CF)
+
+#ifdef CONFIG_X86_32
+# define FIX_EFLAGS (__FIX_EFLAGS | X86_EFLAGS_RF)
+#else
+# define FIX_EFLAGS __FIX_EFLAGS
+#endif
+
+#define COPY(x) do { \
+ get_user_ex(regs->x, &sc->x); \
+} while (0)
+
+#define GET_SEG(seg) ({ \
+ unsigned short tmp; \
+ get_user_ex(tmp, &sc->seg); \
+ tmp; \
+})
+
+#define COPY_SEG(seg) do { \
+ regs->seg = GET_SEG(seg); \
+} while (0)
+
+#define COPY_SEG_CPL3(seg) do { \
+ regs->seg = GET_SEG(seg) | 3; \
+} while (0)
+
+
+static inline int
+xnshadow_restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
+ unsigned long *pax)
+{
+ void __user *buf;
+ unsigned int tmpflags;
+ unsigned int err = 0;
+
+ get_user_try {
+
+ set_user_gs(regs, GET_SEG(gs));
+ COPY_SEG(fs);
+ COPY_SEG(es);
+ COPY_SEG(ds);
+
+ COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
+ COPY(dx); COPY(cx); COPY(ip);
+
+ COPY_SEG_CPL3(cs);
+ COPY_SEG_CPL3(ss);
+
+ get_user_ex(tmpflags, &sc->flags);
+ regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
+ regs->orig_ax = -1; /* disable syscall checks */
+
+ get_user_ex(buf, &sc->fpstate);
+
+ /* Do we have to disable / enable preemption here? */
+ if (buf)
+ xnpod_restore_fpu(buf);
+
+ get_user_ex(*pax, &sc->ax);
+ } get_user_catch(err);
+
+ return err;
+}
+
+static inline int xnshadow_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
+ struct pt_regs *regs, unsigned long mask)
+{
+ int err = 0;
+
+ put_user_try {
+
+ put_user_ex(get_user_gs(regs), (unsigned int __user *)&sc->gs);
+ put_user_ex(regs->fs, (unsigned int __user *)&sc->fs);
+ put_user_ex(regs->es, (unsigned int __user *)&sc->es);
+ put_user_ex(regs->ds, (unsigned int __user *)&sc->ds);
+
+ put_user_ex(regs->di, &sc->di);
+ put_user_ex(regs->si, &sc->si);
+ put_user_ex(regs->bp, &sc->bp);
+ put_user_ex(regs->sp, &sc->sp);
+ put_user_ex(regs->bx, &sc->bx);
+ put_user_ex(regs->dx, &sc->dx);
+ put_user_ex(regs->cx, &sc->cx);
+ put_user_ex(regs->ax, &sc->ax);
+
+ put_user_ex(current->thread.trap_no, &sc->trapno);
+ put_user_ex(current->thread.error_code, &sc->err);
+ put_user_ex(regs->ip, &sc->ip);
+ put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
+ put_user_ex(regs->flags, &sc->flags);
+ put_user_ex(regs->sp, &sc->sp_at_signal);
+ put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
+
+ put_user_ex(fpstate, &sc->fpstate);
+
+ /* non-iBCS2 extensions.. */
+ put_user_ex(mask, &sc->oldmask);
+ put_user_ex(current->thread.cr2, &sc->cr2);
+ } put_user_catch(err);
+
+ return err;
+}
+
+static inline long xnshadow_rt_sigreturn(struct pt_regs *regs)
+{
+ struct xnthread *cur;
+ struct rt_sigframe __user *frame;
+ unsigned long ax;
+
+ frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
+ if (!access_rok(frame, sizeof(*frame)))
+ goto badframe;
+
+ if (xnshadow_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
+ goto badframe;
+
+ return ax;
+
+badframe:
+ /* TODO: what can we do when we have a bad frame? */
+ cur = xnshadow_thread(current);
+ if (likely(cur != NULL))
+ xnshadow_call_mayday(cur, SIGDEBUG_WATCHDOG);
+
+ return 0;
+}
+
+static inline void __user *
+xnshadow_get_sigframe(struct pt_regs *regs, size_t frame_size,
+ void __user **fpstate)
+{
+ /* Default to using normal stack */
+ unsigned long sp = regs->sp;
+
+ if (wrap_test_fpu_used(current)) {
+ sp -= sizeof(x86_fpustate);
+ *fpstate = (void __user *)sp;
+ }
+
+ /* Offset the stackpointer so there is room for the frame and align */
+ sp = ((sp - frame_size + 4) & -16ul) - 4;
+
+ /* save i387 state */
+ if (wrap_test_fpu_used(current))
+ xnpod_save_fpu(*fpstate);
+
+ return (void __user *)sp;
+}
+
+static const struct {
+ u8 movl;
+ u32 val;
+ u16 int80;
+ u8 pad;
+} __attribute__((packed)) rt_retcode = {
+ 0xb8, /* movl $..., %eax */
+ __NR_rt_sigreturn,
+ 0x80cd, /* int $0x80 */
+ 0
+};
+
+static inline int xnshadow_setup_rt_frame(int sig, void *handler, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs, void __user *restorer)
+{
+ struct rt_sigframe __user *frame;
+ int err = 0;
+ void __user *fpstate = NULL;
+
+ frame = xnshadow_get_sigframe(regs, sizeof(*frame), &fpstate);
+ if (!access_wok(frame, sizeof(*frame)))
+ return -EFAULT;
+
+ put_user_try {
+ put_user_ex(sig, &frame->sig);
+ put_user_ex(&frame->info, &frame->pinfo);
+ put_user_ex(&frame->uc, &frame->puc);
+ err |= copy_siginfo_to_user(&frame->info, info);
+
+ /* Create the ucontext. */
+ if (cpu_has_xsave)
+ put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+ else
+ put_user_ex(0, &frame->uc.uc_flags);
+ put_user_ex(0, &frame->uc.uc_link);
+ put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ put_user_ex(sas_ss_flags(regs->sp),
+ &frame->uc.uc_stack.ss_flags);
+ put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= xnshadow_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
+ regs, set->sig[0]);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ /* Set up to return from userspace. */
+ put_user_ex(restorer, &frame->pretcode);
+
+ /*
+ * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
+ *
+ * WE DO NOT USE IT ANY MORE! It's only left here for historical
+ * reasons and because gdb uses it as a signature to notice
+ * signal handler stack frames.
+ */
+ put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
+ } put_user_catch(err);
+
+ if (err)
+ return -EFAULT;
+
+ /* Set up registers for signal handler */
+ regs->sp = (unsigned long)frame;
+ regs->ip = (unsigned long)handler;
+ regs->ax = (unsigned long)sig;
+ regs->dx = (unsigned long)&frame->info;
+ regs->cx = (unsigned long)&frame->uc;
+
+ regs->ds = __USER_DS;
+ regs->es = __USER_DS;
+ regs->ss = __USER_DS;
+ regs->cs = __USER_CS;
+
+ return 0;
+}
+
+static inline int xnshadow_setup_trap_info(unsigned int vector,
+ struct pt_regs *regs, long errcode, int *sig, siginfo_t *info)
+{
+ switch (vector) {
+
+ case 0: /* divide_error */
+ *sig = SIGFPE;
+ info->si_signo = *sig;
+ info->si_errno = 0;
+ info->si_code = FPE_INTDIV;
+ info->si_addr = (void __user *)regs->ip;
+ return 0;
+ case 6: /* invalid_op */
+ *sig = SIGILL;
+ info->si_signo = *sig;
+ info->si_errno = 0;
+ info->si_code = ILL_ILLOPN;
+ info->si_addr = (void __user *)regs->ip;
+ return 0;
+ case 9: /* coprocessor_segment_overrun */
+ *sig = SIGFPE;
+ return 0;
+ case 16: { /* coprocessor_error */
+ unsigned short cwd, swd, err;
+ xnarchtcb_t *tcb;
+
+ *sig = SIGFPE;
+ /*
+ * Save the info for the exception handler and clear the error.
+ */
+ tcb = xnthread_archtcb(xnpod_current_thread());
+ xnpod_save_fpu(NULL);
+
+ info->si_signo = *sig;
+ info->si_errno = 0;
+ info->si_addr = (void __user *)regs->ip;
+ /*
+ * (~cwd & swd) will mask out exceptions that are not set to unmasked
+ * status. 0x3f is the exception bits in these regs, 0x200 is the
+ * C1 reg you need in case of a stack fault, 0x040 is the stack
+ * fault bit. We should only be taking one exception at a time,
+ * so if this combination doesn't produce any single exception,
+ * then we have a bad program that isn't synchronizing its FPU usage
+ * and it will suffer the consequences since we won't be able to
+ * fully reproduce the context of the exception
+ */
+ if (cpu_has_fxsr) {
+ cwd = tcb->fpup->fxsave.cwd;
+ swd = tcb->fpup->fxsave.swd;
+ } else {
+ cwd = tcb->fpup->fsave.cwd;
+ swd = tcb->fpup->fsave.swd;
+ }
+ err = swd & ~cwd;
+
+ if (err & 0x001) { /* Invalid op */
+ /*
+ * swd & 0x240 == 0x040: Stack Underflow
+ * swd & 0x240 == 0x240: Stack Overflow
+ * User must clear the SF bit (0x40) if set
+ */
+ info->si_code = FPE_FLTINV;
+ } else if (err & 0x004) { /* Divide by Zero */
+ info->si_code = FPE_FLTDIV;
+ } else if (err & 0x008) { /* Overflow */
+ info->si_code = FPE_FLTOVF;
+ } else if (err & 0x012) { /* Denormal, Underflow */
+ info->si_code = FPE_FLTUND;
+ } else if (err & 0x020) { /* Precision */
+ info->si_code = FPE_FLTRES;
+ } else {
+ /*
+ * If we're using IRQ 13, or supposedly even some trap 16
+ * implementations, it's possible we get a spurious trap...
+ */
+ return -ENOSYS; /* Spurious trap, no error */
+ }
+ return 0;
+ }
+ default:
+ break;
+ }
+ return -ENOSYS;
+}
+
#endif /* XNARCH_HAVE_MAYDAY */
#endif /* !_XENO_ASM_X86_BITS_SHADOW_32_H */
diff --git a/include/asm-x86/bits/shadow_64.h b/include/asm-x86/bits/shadow_64.h
index 69881db..a53994b 100644
--- a/include/asm-x86/bits/shadow_64.h
+++ b/include/asm-x86/bits/shadow_64.h
@@ -121,6 +121,23 @@ static inline void xnarch_fixup_mayday(struct xnarchtcb *tcb,
regs->r9 = tcb->mayday.r9;
}
+static inline int xnshadow_setup_trap_info(unsigned int vector,
+ struct pt_regs *regs, long errcode, int *sig, siginfo_t *info)
+{
+ return -ENOSYS;
+}
+
+static inline int xnshadow_setup_rt_frame(int sig, void *handler, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs, void __user *restorer)
+{
+ return -ENOSYS;
+}
+
+static inline long xnshadow_rt_sigreturn(struct pt_regs *regs)
+{
+ return -ENOSYS;
+}
+
#endif /* XNARCH_HAVE_MAYDAY */
#endif /* !_XENO_ASM_X86_BITS_SHADOW_64_H */
diff --git a/include/native/misc.h b/include/native/misc.h
index 00c4a72..115da49 100644
--- a/include/native/misc.h
+++ b/include/native/misc.h
@@ -92,6 +92,8 @@ extern "C" {
/* Public interface. */
+int rt_sigaction(int signum, void *action);
+
int rt_io_get_region(RT_IOREGION *iorn,
const char *name,
uint64_t start,
diff --git a/include/native/syscall.h b/include/native/syscall.h
index 2e3d7ec..df9b259 100644
--- a/include/native/syscall.h
+++ b/include/native/syscall.h
@@ -128,6 +128,7 @@
#define __native_buffer_inquire 102
#define __native_queue_flush 103
#define __native_cond_wait_epilogue 104
+#define __native_sigaction 105
struct rt_arg_bulk {
diff --git a/include/nucleus/pod.h b/include/nucleus/pod.h
index 056e376..2701946 100644
--- a/include/nucleus/pod.h
+++ b/include/nucleus/pod.h
@@ -135,6 +135,8 @@ void __xnpod_reset_thread(struct xnthread *thread);
#ifdef CONFIG_XENO_HW_FPU
void xnpod_switch_fpu(xnsched_t *sched);
+void xnpod_save_fpu(void __user *buf);
+void xnpod_restore_fpu(void __user *buf);
#endif /* CONFIG_XENO_HW_FPU */
void __xnpod_schedule(struct xnsched *sched);
diff --git a/include/nucleus/ppd.h b/include/nucleus/ppd.h
index 972b0f2..7e9f19a 100644
--- a/include/nucleus/ppd.h
+++ b/include/nucleus/ppd.h
@@ -16,6 +16,7 @@ typedef struct xnshadow_ppd_t {
xnholder_t link;
#ifdef XNARCH_HAVE_MAYDAY
unsigned long mayday_addr;
+ void *sighand[_NSIG];
#endif
#define link2ppd(ln) container_of(ln, xnshadow_ppd_t, link)
} xnshadow_ppd_t;
diff --git a/include/nucleus/shadow.h b/include/nucleus/shadow.h
index cd88522..6697f45 100644
--- a/include/nucleus/shadow.h
+++ b/include/nucleus/shadow.h
@@ -112,7 +112,10 @@ void xnshadow_clear_sig(struct xnthread *thread, unsigned muxid);
#ifdef RTHAL_HAVE_RETURN_EVENT
#define XNARCH_HAVE_MAYDAY 1
+#define XNSHADOW_MD_MAYDAYRETURN_OFFS 0
+#define XNSHADOW_MD_SIGRETURN_OFFS 50
void xnshadow_call_mayday(struct xnthread *thread, int sigtype);
+int xnshadow_handle_rt_signals(unsigned int vector, struct pt_regs *regs, long errcode);
#else
static inline void xnshadow_call_mayday(struct xnthread *thread,
int sigtype)
diff --git a/ksrc/nucleus/pod.c b/ksrc/nucleus/pod.c
index b5ddbaa..1bae36c 100644
--- a/ksrc/nucleus/pod.c
+++ b/ksrc/nucleus/pod.c
@@ -166,6 +166,25 @@ static inline int __xnpod_fault_init_fpu(struct xnthread *thread)
return 0;
}
+void xnpod_save_fpu(void __user *buf)
+{
+ xnarch_save_fpu(xnthread_archtcb(xnpod_current_thread()));
+ if (buf)
+ __xn_safe_copy_to_user(buf,
+ xnthread_archtcb(xnpod_current_thread())->fpup,
+ sizeof(*xnthread_archtcb(xnpod_current_thread())->fpup));
+}
+
+void xnpod_restore_fpu(void __user *buf)
+{
+ /* TODO: should we do locking/preempt disable? */
+ if (!buf || __xn_safe_copy_from_user(
+ xnthread_archtcb(xnpod_current_thread())->fpup, buf,
+ sizeof(*xnthread_archtcb(xnpod_current_thread())->fpup)))
+ return;
+ xnarch_restore_fpu(xnthread_archtcb(xnpod_current_thread()));
+}
+
#else /* !CONFIG_XENO_HW_FPU */
static inline void __xnpod_init_fpu(struct xnsched *sched,
@@ -2625,6 +2644,12 @@ int xnpod_trap_fault(xnarch_fltinfo_t *fltinfo)
xnarch_fault_pc(fltinfo),
xnthread_user_pid(thread));
#endif /* XENO_DEBUG(NUCLEUS) */
+
+ /* It might be we have to handle this fault in realtime */
+ if (xnshadow_handle_rt_signals(xnarch_fault_trap(fltinfo),
+ fltinfo->regs, xnarch_fault_code(fltinfo)))
+ return 1;
+
if (xnarch_fault_pf_p(fltinfo))
/* The page fault counter is not SMP-safe, but it's a
simple indicator that something went wrong wrt memory
diff --git a/ksrc/nucleus/shadow.c b/ksrc/nucleus/shadow.c
index d8d7116..5264a50 100644
--- a/ksrc/nucleus/shadow.c
+++ b/ksrc/nucleus/shadow.c
@@ -1675,6 +1675,46 @@ static int xnshadow_sys_mayday(struct pt_regs *regs)
return -EPERM;
}
+static int xnshadow_sys_rt_sig_return(struct pt_regs *regs)
+{
+ xnshadow_rt_sigreturn(regs);
+
+ return 0;
+}
+
+int xnshadow_handle_rt_signals(unsigned int vector, struct pt_regs *regs, long errcode)
+{
+ int sig = 0;
+ struct xnshadow_ppd_t *sys_ppd;
+ siginfo_t info;
+ sigset_t set;
+ int rval;
+
+ /* Check if we can get a signo for the vector */
+ rval = xnshadow_setup_trap_info(vector, regs, errcode, &sig, &info);
+ if (rval || !sig)
+ return 0;
+
+ /* We enter the event handler with hw IRQs off. */
+ xnlock_get(&nklock);
+ sys_ppd = xnshadow_ppd_get(0);
+ xnlock_put(&nklock);
+ XENO_BUGON(NUCLEUS, sys_ppd == NULL);
+
+ /* Check if we have a handler installed for this sig */
+ if (!sys_ppd->sighand[sig] || (sys_ppd->sighand[sig] == SIG_DFL))
+ return 0;
+
+ /* Signal delivery */
+ rval = xnshadow_setup_rt_frame(sig, sys_ppd->sighand[sig], &info, &set, regs,
+ (void *)(sys_ppd->mayday_addr + XNSHADOW_MD_SIGRETURN_OFFS));
+
+ if (rval)
+ return 0;
+ else
+ return 1;
+}
+
static inline int mayday_init_page(void)
{
mayday_page = vmalloc(PAGE_SIZE);
@@ -1706,7 +1746,8 @@ static inline void do_mayday_event(struct pt_regs *regs)
xnlock_put(&nklock);
XENO_BUGON(NUCLEUS, sys_ppd == NULL);
- xnarch_handle_mayday(tcb, regs, sys_ppd->mayday_addr);
+ xnarch_handle_mayday(tcb, regs,
+ sys_ppd->mayday_addr + XNSHADOW_MD_MAYDAYRETURN_OFFS);
}
RTHAL_DECLARE_MAYDAY_EVENT(mayday_event);
@@ -1727,6 +1768,10 @@ static inline void mayday_cleanup_page(void)
{
}
+static int xnshadow_sys_rt_sig_return(struct pt_regs *regs)
+{
+ return -ENOSYS;
+}
#endif /* XNARCH_HAVE_MAYDAY */
static int xnshadow_sys_bind(struct pt_regs *regs)
@@ -1829,6 +1874,11 @@ static int xnshadow_sys_bind(struct pt_regs *regs)
err = -ENOMEM;
goto fail_destroy_sys_ppd;
}
+ {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(sys_ppd->sighand); i++)
+ sys_ppd->sighand[i] = 0;
+ }
#endif /* XNARCH_HAVE_MAYDAY */
if (ppd_insert(sys_ppd) == -EBUSY) {
@@ -2160,6 +2210,7 @@ static xnsysent_t __systab[] = {
[__xn_sys_drop_u_mode] =
{&xnshadow_sys_drop_u_mode, __xn_exec_shadow},
[__xn_sys_mayday] = {&xnshadow_sys_mayday, __xn_exec_any|__xn_exec_norestart},
+ [__xn_sys_rt_sig_return] = {&xnshadow_sys_rt_sig_return, __xn_exec_primary|__xn_exec_norestart},
};
static void post_ppd_release(struct xnheap *h)
diff --git a/ksrc/skins/native/syscall.c b/ksrc/skins/native/syscall.c
index e6c4257..324f8dc 100644
--- a/ksrc/skins/native/syscall.c
+++ b/ksrc/skins/native/syscall.c
@@ -3972,6 +3972,29 @@ static int __rt_io_put_region(struct pt_regs *regs)
return 0;
}
+static int __rt_sigaction(struct pt_regs *regs)
+{
+ int signum = 0;
+ void *handler = NULL;
+ struct xnshadow_ppd_t *sys_ppd;
+
+ /* We enter the event handler with hw IRQs off. */
+ xnlock_get(&nklock);
+ sys_ppd = xnshadow_ppd_get(0);
+ xnlock_put(&nklock);
+ XENO_BUGON(NUCLEUS, sys_ppd == NULL);
+
+ if (__xn_safe_copy_from_user(&signum, (void __user *)__xn_reg_arg1(regs),
+ sizeof(signum)))
+ return -EFAULT;
+ if (__xn_safe_copy_from_user(&handler, (void __user *)__xn_reg_arg2(regs),
+ sizeof(handler)))
+ return -EFAULT;
+
+ sys_ppd->sighand[signum] = handler;
+ return 0;
+}
+
static __attribute__ ((unused))
int __rt_call_not_available(struct pt_regs *regs)
{
@@ -4147,6 +4170,7 @@ static xnsysent_t __systab[] = {
[__native_buffer_write] = {&__rt_buffer_write, __xn_exec_conforming},
[__native_buffer_clear] = {&__rt_buffer_clear, __xn_exec_any},
[__native_buffer_inquire] = {&__rt_buffer_inquire, __xn_exec_any},
+ [__native_sigaction] = {&__rt_sigaction, __xn_exec_any},
};
static struct xnskin_props __props = {
diff --git a/src/skins/native/misc.c b/src/skins/native/misc.c
index 1570d14..71bfee0 100644
--- a/src/skins/native/misc.c
+++ b/src/skins/native/misc.c
@@ -18,9 +18,16 @@
#include <native/syscall.h>
#include <native/misc.h>
+/* #include <signal.h> */
extern int __native_muxid;
+int rt_sigaction(int signum, void *action)
+{
+ return XENOMAI_SKINCALL2(__native_muxid,
+ __native_sigaction, &signum, &action);
+}
+
int rt_io_get_region(RT_IOREGION *iorn, const char *name,
uint64_t start, uint64_t len, int flags)
{
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help