mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 14:52:05 +00:00
openrisc: Support storing and restoring fpu state
OpenRISC floating point state is not so expensive to save as OpenRISC uses general purpose registers for floating point instructions. We need to save only the floating point status and control register, FPCSR. Add support to maintain the FPCSR unconditionally upon exceptions and switches. On machines that do not support FPU this will always just store 0x0 and restore is a no-op. On FPU systems this adds an additional special purpose register read/write and read/write to memory (already cached). Signed-off-by: Stafford Horne <shorne@gmail.com>
This commit is contained in:
parent
812489ac4d
commit
63d7f9f11e
@ -59,7 +59,7 @@ struct pt_regs {
|
|||||||
* -1 for all other exceptions.
|
* -1 for all other exceptions.
|
||||||
*/
|
*/
|
||||||
long orig_gpr11; /* For restarting system calls */
|
long orig_gpr11; /* For restarting system calls */
|
||||||
long dummy; /* Cheap alignment fix */
|
long fpcsr; /* Floating point control status register. */
|
||||||
long dummy2; /* Cheap alignment fix */
|
long dummy2; /* Cheap alignment fix */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -115,6 +115,6 @@ static inline long regs_return_value(struct pt_regs *regs)
|
|||||||
#define PT_GPR31 124
|
#define PT_GPR31 124
|
||||||
#define PT_PC 128
|
#define PT_PC 128
|
||||||
#define PT_ORIG_GPR11 132
|
#define PT_ORIG_GPR11 132
|
||||||
#define PT_SYSCALLNO 136
|
#define PT_FPCSR 136
|
||||||
|
|
||||||
#endif /* __ASM_OPENRISC_PTRACE_H */
|
#endif /* __ASM_OPENRISC_PTRACE_H */
|
||||||
|
@ -106,6 +106,8 @@
|
|||||||
l.mtspr r0,r3,SPR_EPCR_BASE ;\
|
l.mtspr r0,r3,SPR_EPCR_BASE ;\
|
||||||
l.lwz r3,PT_SR(r1) ;\
|
l.lwz r3,PT_SR(r1) ;\
|
||||||
l.mtspr r0,r3,SPR_ESR_BASE ;\
|
l.mtspr r0,r3,SPR_ESR_BASE ;\
|
||||||
|
l.lwz r3,PT_FPCSR(r1) ;\
|
||||||
|
l.mtspr r0,r3,SPR_FPCSR ;\
|
||||||
l.lwz r2,PT_GPR2(r1) ;\
|
l.lwz r2,PT_GPR2(r1) ;\
|
||||||
l.lwz r3,PT_GPR3(r1) ;\
|
l.lwz r3,PT_GPR3(r1) ;\
|
||||||
l.lwz r4,PT_GPR4(r1) ;\
|
l.lwz r4,PT_GPR4(r1) ;\
|
||||||
@ -175,6 +177,8 @@ handler: ;\
|
|||||||
/* r30 already save */ ;\
|
/* r30 already save */ ;\
|
||||||
l.sw PT_GPR31(r1),r31 ;\
|
l.sw PT_GPR31(r1),r31 ;\
|
||||||
TRACE_IRQS_OFF_ENTRY ;\
|
TRACE_IRQS_OFF_ENTRY ;\
|
||||||
|
l.mfspr r30,r0,SPR_FPCSR ;\
|
||||||
|
l.sw PT_FPCSR(r1),r30 ;\
|
||||||
/* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\
|
/* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\
|
||||||
l.addi r30,r0,-1 ;\
|
l.addi r30,r0,-1 ;\
|
||||||
l.sw PT_ORIG_GPR11(r1),r30
|
l.sw PT_ORIG_GPR11(r1),r30
|
||||||
@ -215,6 +219,8 @@ handler: ;\
|
|||||||
/* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\
|
/* Store -1 in orig_gpr11 for non-syscall exceptions */ ;\
|
||||||
l.addi r30,r0,-1 ;\
|
l.addi r30,r0,-1 ;\
|
||||||
l.sw PT_ORIG_GPR11(r1),r30 ;\
|
l.sw PT_ORIG_GPR11(r1),r30 ;\
|
||||||
|
l.mfspr r30,r0,SPR_FPCSR ;\
|
||||||
|
l.sw PT_FPCSR(r1),r30 ;\
|
||||||
l.addi r3,r1,0 ;\
|
l.addi r3,r1,0 ;\
|
||||||
/* r4 is exception EA */ ;\
|
/* r4 is exception EA */ ;\
|
||||||
l.addi r5,r0,vector ;\
|
l.addi r5,r0,vector ;\
|
||||||
@ -1087,6 +1093,10 @@ ENTRY(_switch)
|
|||||||
l.sw PT_GPR28(r1),r28
|
l.sw PT_GPR28(r1),r28
|
||||||
l.sw PT_GPR30(r1),r30
|
l.sw PT_GPR30(r1),r30
|
||||||
|
|
||||||
|
/* Store the old FPU state to new pt_regs */
|
||||||
|
l.mfspr r29,r0,SPR_FPCSR
|
||||||
|
l.sw PT_FPCSR(r1),r29
|
||||||
|
|
||||||
l.addi r11,r10,0 /* Save old 'current' to 'last' return value*/
|
l.addi r11,r10,0 /* Save old 'current' to 'last' return value*/
|
||||||
|
|
||||||
/* We use thread_info->ksp for storing the address of the above
|
/* We use thread_info->ksp for storing the address of the above
|
||||||
@ -1109,6 +1119,10 @@ ENTRY(_switch)
|
|||||||
l.lwz r29,PT_SP(r1)
|
l.lwz r29,PT_SP(r1)
|
||||||
l.sw TI_KSP(r10),r29
|
l.sw TI_KSP(r10),r29
|
||||||
|
|
||||||
|
/* Restore the old value of FPCSR */
|
||||||
|
l.lwz r29,PT_FPCSR(r1)
|
||||||
|
l.mtspr r0,r29,SPR_FPCSR
|
||||||
|
|
||||||
/* ...and restore the registers, except r11 because the return value
|
/* ...and restore the registers, except r11 because the return value
|
||||||
* has already been set above.
|
* has already been set above.
|
||||||
*/
|
*/
|
||||||
|
@ -75,8 +75,9 @@ void show_registers(struct pt_regs *regs)
|
|||||||
in_kernel = 0;
|
in_kernel = 0;
|
||||||
|
|
||||||
printk("CPU #: %d\n"
|
printk("CPU #: %d\n"
|
||||||
" PC: %08lx SR: %08lx SP: %08lx\n",
|
" PC: %08lx SR: %08lx SP: %08lx FPCSR: %08lx\n",
|
||||||
smp_processor_id(), regs->pc, regs->sr, regs->sp);
|
smp_processor_id(), regs->pc, regs->sr, regs->sp,
|
||||||
|
regs->fpcsr);
|
||||||
printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
|
printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
|
||||||
0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
|
0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
|
||||||
printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
|
printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user