mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-05-24 10:39:52 +00:00
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: Stafford Horne <shorne@gmail.com>
This commit is contained in:
parent
63d7f9f11e
commit
27267655c5
7 changed files with 41 additions and 6 deletions
|
@ -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 {
|
||||||
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 @@
|
||||||
|
|
||||||
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:
|
||||||
|
|
||||||
/******* 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:
|
||||||
.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,
|
||||||
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(®s->pc, &sc->regs.pc, sizeof(unsigned long));
|
err |= __copy_from_user(®s->pc, &sc->regs.pc, sizeof(unsigned long));
|
||||||
err |= __copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long));
|
err |= __copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long));
|
||||||
|
err |= __copy_from_user(®s->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)
|
||||||
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, ®s->pc, sizeof(unsigned long));
|
err |= __copy_to_user(&sc->regs.pc, ®s->pc, sizeof(unsigned long));
|
||||||
err |= __copy_to_user(&sc->regs.sr, ®s->sr, sizeof(unsigned long));
|
err |= __copy_to_user(&sc->regs.sr, ®s->sr, sizeof(unsigned long));
|
||||||
|
err |= __copy_to_user(&sc->fpu.fpcsr, ®s->fpcsr, sizeof(unsigned long));
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue