summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/kernel/osf_sys.c40
-rw-r--r--include/asm-alpha/sysinfo.h1
2 files changed, 31 insertions, 10 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index b45caf6aff9c..762a528bf20e 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -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;
}
diff --git a/include/asm-alpha/sysinfo.h b/include/asm-alpha/sysinfo.h
index 1c65a021ac3b..086aba284df2 100644
--- a/include/asm-alpha/sysinfo.h
+++ b/include/asm-alpha/sysinfo.h
@@ -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