Skip to content

Commit 2726765

Browse files
committed
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>
1 parent 63d7f9f commit 2726765

7 files changed

Lines changed: 41 additions & 6 deletions

File tree

arch/openrisc/include/uapi/asm/elf.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ typedef unsigned long elf_greg_t;
5353
#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
5454
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
5555

56-
/* A placeholder; OR32 does not have fp support yes, so no fp regs for now. */
57-
typedef unsigned long elf_fpregset_t;
56+
typedef struct __or1k_fpu_state elf_fpregset_t;
5857

5958
/* EM_OPENRISC is defined in linux/elf-em.h */
6059
#define EM_OR32 0x8472

arch/openrisc/include/uapi/asm/ptrace.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ struct user_regs_struct {
3030
unsigned long pc;
3131
unsigned long sr;
3232
};
33+
34+
struct __or1k_fpu_state {
35+
unsigned long fpcsr;
36+
};
3337
#endif
3438

3539

arch/openrisc/include/uapi/asm/sigcontext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
struct sigcontext {
3030
struct user_regs_struct regs; /* needs to be first */
31+
struct __or1k_fpu_state fpu;
3132
unsigned long oldmask;
3233
};
3334

arch/openrisc/kernel/entry.S

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -848,9 +848,16 @@ _syscall_badsys:
848848

849849
/******* END SYSCALL HANDLING *******/
850850

851-
/* ---[ 0xd00: Trap exception ]------------------------------------------ */
851+
/* ---[ 0xd00: Floating Point exception ]-------------------------------- */
852852

853-
UNHANDLED_EXCEPTION(_vector_0xd00,0xd00)
853+
EXCEPTION_ENTRY(_fpe_trap_handler)
854+
CLEAR_LWA_FLAG(r3)
855+
/* r4: EA of fault (set by EXCEPTION_HANDLE) */
856+
l.jal do_fpe_trap
857+
l.addi r3,r1,0 /* pt_regs */
858+
859+
l.j _ret_from_exception
860+
l.nop
854861

855862
/* ---[ 0xe00: Trap exception ]------------------------------------------ */
856863

arch/openrisc/kernel/head.S

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,9 @@ _dispatch_do_ipage_fault:
424424
.org 0xc00
425425
EXCEPTION_HANDLE(_sys_call_handler)
426426

427-
/* ---[ 0xd00: Trap exception ]------------------------------------------ */
427+
/* ---[ 0xd00: Floating point exception ]--------------------------------- */
428428
.org 0xd00
429-
UNHANDLED_EXCEPTION(_vector_0xd00)
429+
EXCEPTION_HANDLE(_fpe_trap_handler)
430430

431431
/* ---[ 0xe00: Trap exception ]------------------------------------------ */
432432
.org 0xe00

arch/openrisc/kernel/signal.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ static int restore_sigcontext(struct pt_regs *regs,
5050
err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long));
5151
err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long));
5252
err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long));
53+
err |= __copy_from_user(&regs->fpcsr, &sc->fpu.fpcsr, sizeof(unsigned long));
5354

5455
/* make sure the SM-bit is cleared so user-mode cannot fool us */
5556
regs->sr &= ~SPR_SR_SM;
@@ -112,6 +113,7 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
112113
err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
113114
err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
114115
err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
116+
err |= __copy_to_user(&sc->fpu.fpcsr, &regs->fpcsr, sizeof(unsigned long));
115117

116118
return err;
117119
}

arch/openrisc/kernel/traps.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,28 @@ asmlinkage void unhandled_exception(struct pt_regs *regs, int ea, int vector)
243243
die("Oops", regs, 9);
244244
}
245245

246+
asmlinkage void do_fpe_trap(struct pt_regs *regs, unsigned long address)
247+
{
248+
int code = FPE_FLTUNK;
249+
unsigned long fpcsr = regs->fpcsr;
250+
251+
if (fpcsr & SPR_FPCSR_IVF)
252+
code = FPE_FLTINV;
253+
else if (fpcsr & SPR_FPCSR_OVF)
254+
code = FPE_FLTOVF;
255+
else if (fpcsr & SPR_FPCSR_UNF)
256+
code = FPE_FLTUND;
257+
else if (fpcsr & SPR_FPCSR_DZF)
258+
code = FPE_FLTDIV;
259+
else if (fpcsr & SPR_FPCSR_IXF)
260+
code = FPE_FLTRES;
261+
262+
/* Clear all flags */
263+
regs->fpcsr &= ~SPR_FPCSR_ALLF;
264+
265+
force_sig_fault(SIGFPE, code, (void __user *)regs->pc);
266+
}
267+
246268
asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
247269
{
248270
force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc);

0 commit comments

Comments
 (0)