Commit 27267655 authored by Stafford Horne's avatar Stafford Horne

openrisc: Support floating point user api

Add support for handling floating point exceptions and forwarding the
SIGFPE signal to processes.  Also, add fpu state to sigcontext.
Signed-off-by: default avatarStafford Horne <shorne@gmail.com>
parent 63d7f9f1
...@@ -53,8 +53,7 @@ typedef unsigned long elf_greg_t; ...@@ -53,8 +53,7 @@ typedef unsigned long elf_greg_t;
#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) #define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef elf_greg_t elf_gregset_t[ELF_NGREG];
/* A placeholder; OR32 does not have fp support yes, so no fp regs for now. */ typedef struct __or1k_fpu_state elf_fpregset_t;
typedef unsigned long elf_fpregset_t;
/* EM_OPENRISC is defined in linux/elf-em.h */ /* EM_OPENRISC is defined in linux/elf-em.h */
#define EM_OR32 0x8472 #define EM_OR32 0x8472
......
...@@ -30,6 +30,10 @@ struct user_regs_struct { ...@@ -30,6 +30,10 @@ struct user_regs_struct {
unsigned long pc; unsigned long pc;
unsigned long sr; unsigned long sr;
}; };
struct __or1k_fpu_state {
unsigned long fpcsr;
};
#endif #endif
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
struct sigcontext { struct sigcontext {
struct user_regs_struct regs; /* needs to be first */ struct user_regs_struct regs; /* needs to be first */
struct __or1k_fpu_state fpu;
unsigned long oldmask; unsigned long oldmask;
}; };
......
...@@ -848,9 +848,16 @@ _syscall_badsys: ...@@ -848,9 +848,16 @@ _syscall_badsys:
/******* END SYSCALL HANDLING *******/ /******* END SYSCALL HANDLING *******/
/* ---[ 0xd00: Trap exception ]------------------------------------------ */ /* ---[ 0xd00: Floating Point exception ]-------------------------------- */
UNHANDLED_EXCEPTION(_vector_0xd00,0xd00) EXCEPTION_ENTRY(_fpe_trap_handler)
CLEAR_LWA_FLAG(r3)
/* r4: EA of fault (set by EXCEPTION_HANDLE) */
l.jal do_fpe_trap
l.addi r3,r1,0 /* pt_regs */
l.j _ret_from_exception
l.nop
/* ---[ 0xe00: Trap exception ]------------------------------------------ */ /* ---[ 0xe00: Trap exception ]------------------------------------------ */
......
...@@ -424,9 +424,9 @@ _dispatch_do_ipage_fault: ...@@ -424,9 +424,9 @@ _dispatch_do_ipage_fault:
.org 0xc00 .org 0xc00
EXCEPTION_HANDLE(_sys_call_handler) EXCEPTION_HANDLE(_sys_call_handler)
/* ---[ 0xd00: Trap exception ]------------------------------------------ */ /* ---[ 0xd00: Floating point exception ]--------------------------------- */
.org 0xd00 .org 0xd00
UNHANDLED_EXCEPTION(_vector_0xd00) EXCEPTION_HANDLE(_fpe_trap_handler)
/* ---[ 0xe00: Trap exception ]------------------------------------------ */ /* ---[ 0xe00: Trap exception ]------------------------------------------ */
.org 0xe00 .org 0xe00
......
...@@ -50,6 +50,7 @@ static int restore_sigcontext(struct pt_regs *regs, ...@@ -50,6 +50,7 @@ static int restore_sigcontext(struct pt_regs *regs,
err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)); err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long));
err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long)); err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long));
err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long)); err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long));
err |= __copy_from_user(&regs->fpcsr, &sc->fpu.fpcsr, sizeof(unsigned long));
/* make sure the SM-bit is cleared so user-mode cannot fool us */ /* make sure the SM-bit is cleared so user-mode cannot fool us */
regs->sr &= ~SPR_SR_SM; regs->sr &= ~SPR_SR_SM;
...@@ -112,6 +113,7 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) ...@@ -112,6 +113,7 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long)); err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long)); err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long)); err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
err |= __copy_to_user(&sc->fpu.fpcsr, &regs->fpcsr, sizeof(unsigned long));
return err; return err;
} }
......
...@@ -243,6 +243,28 @@ asmlinkage void unhandled_exception(struct pt_regs *regs, int ea, int vector) ...@@ -243,6 +243,28 @@ asmlinkage void unhandled_exception(struct pt_regs *regs, int ea, int vector)
die("Oops", regs, 9); die("Oops", regs, 9);
} }
asmlinkage void do_fpe_trap(struct pt_regs *regs, unsigned long address)
{
int code = FPE_FLTUNK;
unsigned long fpcsr = regs->fpcsr;
if (fpcsr & SPR_FPCSR_IVF)
code = FPE_FLTINV;
else if (fpcsr & SPR_FPCSR_OVF)
code = FPE_FLTOVF;
else if (fpcsr & SPR_FPCSR_UNF)
code = FPE_FLTUND;
else if (fpcsr & SPR_FPCSR_DZF)
code = FPE_FLTDIV;
else if (fpcsr & SPR_FPCSR_IXF)
code = FPE_FLTRES;
/* Clear all flags */
regs->fpcsr &= ~SPR_FPCSR_ALLF;
force_sig_fault(SIGFPE, code, (void __user *)regs->pc);
}
asmlinkage void do_trap(struct pt_regs *regs, unsigned long address) asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
{ {
force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc); force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc);
......
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