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:
Stafford Horne 2023-04-14 08:27:51 +01:00
Родитель 63d7f9f11e
Коммит 27267655c5
7 изменённых файлов: 41 добавлений и 6 удалений

Просмотреть файл

@ -53,8 +53,7 @@ typedef unsigned long elf_greg_t;
#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
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 unsigned long elf_fpregset_t;
typedef struct __or1k_fpu_state elf_fpregset_t;
/* EM_OPENRISC is defined in linux/elf-em.h */
#define EM_OR32 0x8472

Просмотреть файл

@ -30,6 +30,10 @@ struct user_regs_struct {
unsigned long pc;
unsigned long sr;
};
struct __or1k_fpu_state {
unsigned long fpcsr;
};
#endif

Просмотреть файл

@ -28,6 +28,7 @@
struct sigcontext {
struct user_regs_struct regs; /* needs to be first */
struct __or1k_fpu_state fpu;
unsigned long oldmask;
};

Просмотреть файл

@ -848,9 +848,16 @@ _syscall_badsys:
/******* 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 ]------------------------------------------ */

Просмотреть файл

@ -424,9 +424,9 @@ _dispatch_do_ipage_fault:
.org 0xc00
EXCEPTION_HANDLE(_sys_call_handler)
/* ---[ 0xd00: Trap exception ]------------------------------------------ */
/* ---[ 0xd00: Floating point exception ]--------------------------------- */
.org 0xd00
UNHANDLED_EXCEPTION(_vector_0xd00)
EXCEPTION_HANDLE(_fpe_trap_handler)
/* ---[ 0xe00: Trap exception ]------------------------------------------ */
.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->pc, &sc->regs.pc, 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 */
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.pc, &regs->pc, 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;
}

Просмотреть файл

@ -243,6 +243,28 @@ asmlinkage void unhandled_exception(struct pt_regs *regs, int ea, int vector)
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)
{
force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc);