Commit f8ab48a7 authored by Richard Henderson's avatar Richard Henderson Committed by Linus Torvalds

[ALPHA] Fix raising of ieee exceptions from userland software.

parent 30bf4cdd
...@@ -723,7 +723,8 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes, ...@@ -723,7 +723,8 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
{ {
switch (op) { switch (op) {
case SSI_IEEE_FP_CONTROL: { case SSI_IEEE_FP_CONTROL: {
unsigned long swcr, fpcr, fex; unsigned long swcr, fpcr;
unsigned int *state;
/* /*
* Alpha Architecture Handbook 4.7.7.3: * Alpha Architecture Handbook 4.7.7.3:
...@@ -732,22 +733,42 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes, ...@@ -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. * set in the trap shadow of a software-complete insn.
*/ */
/* Update softare trap enable bits. */
if (get_user(swcr, (unsigned long __user *)buffer)) if (get_user(swcr, (unsigned long __user *)buffer))
return -EFAULT; return -EFAULT;
current_thread_info()->ieee_state state = &current_thread_info()->ieee_state;
= ((current_thread_info()->ieee_state & ~IEEE_SW_MASK)
| (swcr & IEEE_SW_MASK)); /* 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. */ /* Update the real fpcr. */
fpcr = rdfpcr(); fpcr = rdfpcr();
fpcr &= FPCR_DYN_MASK;
fpcr |= ieee_swcr_to_fpcr(swcr); fpcr |= ieee_swcr_to_fpcr(swcr);
wrfpcr(fpcr); wrfpcr(fpcr);
/* If any exceptions are now unmasked, send a signal. */ /* If any exceptions set by this call, and are unmasked,
fex = ((swcr & IEEE_STATUS_MASK) send a signal. Old exceptions are not signaled. */
>> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr; fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
if (fex) { if (fex) {
siginfo_t info; siginfo_t info;
int si_code = 0; int si_code = 0;
...@@ -765,7 +786,6 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes, ...@@ -765,7 +786,6 @@ osf_setsysinfo(unsigned long op, void __user *buffer, unsigned long nbytes,
info.si_addr = NULL; /* FIXME */ info.si_addr = NULL; /* FIXME */
send_sig_info(SIGFPE, &info, current); send_sig_info(SIGFPE, &info, current);
} }
return 0; return 0;
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define SSI_IEEE_FP_CONTROL 14 #define SSI_IEEE_FP_CONTROL 14
#define SSI_IEEE_STATE_AT_SIGNAL 15 #define SSI_IEEE_STATE_AT_SIGNAL 15
#define SSI_IEEE_IGNORE_STATE_AT_SIGNAL 16 #define SSI_IEEE_IGNORE_STATE_AT_SIGNAL 16
#define SSI_IEEE_RAISE_EXCEPTION 1001 /* linux specific */
#define SSIN_UACPROC 6 #define SSIN_UACPROC 6
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment