]> git.hungrycats.org Git - linux/commitdiff
[ALPHA] Fix raising of ieee exceptions from userland software.
authorRichard Henderson <rth@kanga.twiddle.home>
Sun, 5 Sep 2004 11:05:06 +0000 (04:05 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sun, 5 Sep 2004 11:05:06 +0000 (04:05 -0700)
arch/alpha/kernel/osf_sys.c
include/asm-alpha/sysinfo.h

index 4761ed9a44c2c84ac1af1d79d6a8ae169d4201a7..545d5453f690f641712804c192cad08bb733a979 100644 (file)
@@ -723,7 +723,8 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
 {
        switch (op) {
        case SSI_IEEE_FP_CONTROL: {
-               unsigned long swcr, fpcr, fex;
+               unsigned long swcr, fpcr;
+               unsigned int *state;
 
                /* 
                 * Alpha Architecture Handbook 4.7.7.3:
@@ -732,22 +733,42 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
                 * set in the trap shadow of a software-complete insn.
                 */
 
-               /* Update softare trap enable bits.  */
                if (get_user(swcr, (unsigned long __user *)buffer))
                        return -EFAULT;
-               current_thread_info()->ieee_state
-                 = ((current_thread_info()->ieee_state & ~IEEE_SW_MASK)
-                    | (swcr & IEEE_SW_MASK));
+               state = &current_thread_info()->ieee_state;
+
+               /* Update softare trap enable bits.  */
+               *state = (*state & ~IEEE_SW_MASK) | (swcr & IEEE_SW_MASK);
+
+               /* Update the real fpcr.  */
+               fpcr = rdfpcr() & FPCR_DYN_MASK;
+               fpcr |= ieee_swcr_to_fpcr(swcr);
+               wrfpcr(fpcr);
+
+               return 0;
+       }
+
+       case SSI_IEEE_RAISE_EXCEPTION: {
+               unsigned long exc, swcr, fpcr, fex;
+               unsigned int *state;
+
+               if (get_user(exc, (unsigned long __user *)buffer))
+                       return -EFAULT;
+               state = &current_thread_info()->ieee_state;
+               exc &= IEEE_STATUS_MASK;
+
+               /* Update softare trap enable bits.  */
+               swcr = (*state & IEEE_SW_MASK) | exc;
+               *state |= exc;
 
                /* Update the real fpcr.  */
                fpcr = rdfpcr();
-               fpcr &= FPCR_DYN_MASK;
                fpcr |= ieee_swcr_to_fpcr(swcr);
                wrfpcr(fpcr);
 
-               /* If any exceptions are now unmasked, send a signal.  */
-               fex = ((swcr & IEEE_STATUS_MASK)
-                      >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
+               /* If any exceptions set by this call, and are unmasked,
+                  send a signal.  Old exceptions are not signaled.  */
+               fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
                if (fex) {
                        siginfo_t info;
                        int si_code = 0;
@@ -765,7 +786,6 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
                        info.si_addr = NULL;  /* FIXME */
                        send_sig_info(SIGFPE, &info, current);
                }
-
                return 0;
        }
 
index 1c65a021ac3b7e305b0f354f49169a7b43eca40d..086aba284df25ba314e246eb2e975291b4191dfa 100644 (file)
@@ -18,6 +18,7 @@
 #define SSI_IEEE_FP_CONTROL            14
 #define SSI_IEEE_STATE_AT_SIGNAL       15
 #define SSI_IEEE_IGNORE_STATE_AT_SIGNAL        16
+#define SSI_IEEE_RAISE_EXCEPTION       1001    /* linux specific */
 
 #define SSIN_UACPROC                   6