summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/i386/linux/linux.h44
-rw-r--r--sys/i386/linux/linux_sysvec.c17
2 files changed, 56 insertions, 5 deletions
diff --git a/sys/i386/linux/linux.h b/sys/i386/linux/linux.h
index 4ac9447..0795e6f 100644
--- a/sys/i386/linux/linux.h
+++ b/sys/i386/linux/linux.h
@@ -135,8 +135,10 @@ struct linux_new_utsname {
#define LINUX_SIGPWR 30
#define LINUX_SIGUNUSED 31
-#define LINUX_NSIG 64
#define LINUX_SIGTBLSZ 31
+#define LINUX_NSIG_WORDS 2
+#define LINUX_NBPW 32
+#define LINUX_NSIG (LINUX_NBPW * LINUX_NSIG_WORDS)
/* sigaction flags */
#define LINUX_SA_NOCLDSTOP 0x00000001
@@ -174,7 +176,7 @@ typedef void (*linux_handler_t)(int);
typedef u_long linux_osigset_t;
typedef struct {
- u_int __bits[2];
+ u_int __bits[LINUX_NSIG_WORDS];
} linux_sigset_t;
typedef struct {
@@ -289,6 +291,42 @@ typedef struct siginfo {
#define lsi_band _sifields._sigpoll._band
#define lsi_fd _sifields._sigpoll._fd
+struct linux_fpreg {
+ u_int16_t significand[4];
+ u_int16_t exponent;
+};
+
+struct linux_fpxreg {
+ u_int16_t significand[4];
+ u_int16_t exponent;
+ u_int16_t padding[3];
+};
+
+struct linux_xmmreg {
+ u_int32_t element[4];
+};
+
+struct linux_fpstate {
+ /* Regular FPU environment */
+ u_int32_t cw;
+ u_int32_t sw;
+ u_int32_t tag;
+ u_int32_t ipoff;
+ u_int32_t cssel;
+ u_int32_t dataoff;
+ u_int32_t datasel;
+ struct linux_fpreg _st[8];
+ u_int16_t status;
+ u_int16_t magic; /* 0xffff = regular FPU data */
+
+ /* FXSR FPU environment */
+ u_int32_t _fxsr_env[6]; /* env is ignored */
+ u_int32_t mxcsr;
+ u_int32_t reserved;
+ struct linux_fpxreg _fxsr_st[8]; /* reg data is ignored */
+ struct linux_xmmreg _xmm[8];
+ u_int32_t padding[56];
+};
/*
* We make the stack look like Linux expects it when calling a signal
@@ -299,6 +337,8 @@ typedef struct siginfo {
struct linux_sigframe {
int sf_sig;
struct linux_sigcontext sf_sc;
+ struct linux_fpstate fpstate;
+ u_int extramask[LINUX_NSIG_WORDS-1];
linux_handler_t sf_handler;
};
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index bf9161e..895a48c 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -345,7 +345,7 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
register struct trapframe *regs;
struct linux_sigframe *fp, frame;
struct sigacts *psp = p->p_sigacts;
- int oonstack;
+ int oonstack, i;
regs = p->p_md.md_regs;
oonstack = p->p_sigstk.ss_flags & SS_ONSTACK;
@@ -425,7 +425,10 @@ linux_sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
frame.sf_sc.sc_ss = regs->tf_ss;
frame.sf_sc.sc_err = regs->tf_err;
frame.sf_sc.sc_trapno = code; /* XXX ???? */
-
+ bzero(&frame.fpstate, sizeof(struct linux_fpstate));
+ for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
+ frame.extramask[i] = mask->__bits[i+1];
+
if (copyout(&frame, fp, sizeof(frame)) != 0) {
/*
* Process has trashed its stack; give it an illegal
@@ -466,7 +469,9 @@ linux_sigreturn(p, args)
{
struct linux_sigcontext context;
register struct trapframe *regs;
- int eflags;
+ u_int extramask[LINUX_NSIG_WORDS-1];
+ u_int *emp;
+ int eflags, i;
regs = p->p_md.md_regs;
@@ -513,6 +518,12 @@ linux_sigreturn(p, args)
}
p->p_sigstk.ss_flags &= ~SS_ONSTACK;
+ emp = (u_int *)((caddr_t)args->scp + sizeof(context) +
+ sizeof(struct linux_fpstate));
+ if (copyin((caddr_t)emp, extramask, sizeof(extramask)) == 0)
+ for (i = 0; i < (LINUX_NSIG_WORDS-1); i++)
+ p->p_sigmask.__bits[i+1] = extramask[i];
+
SIGSETOLD(p->p_sigmask, context.sc_mask);
SIG_CANTMASK(p->p_sigmask);
OpenPOWER on IntegriCloud