powerpc: Allow emulating optional FPU instructions on CPUs with an FPU
The e5500 has an FPU, but lacks the optional fsqrt instruction. This instruction gets emulated in the kernel, but the emulation uses stale data, from the last switch out, and does not return the result of the operation immediately. Fix both of these conditions by saving and restoring the FPRs around the emulation point. MFC after: 1 week MFC with: r345829
This commit is contained in:
parent
b0fefb25c5
commit
62c7ea1f1d
@ -152,10 +152,10 @@
|
||||
|
||||
#ifndef LOCORE
|
||||
struct trapframe;
|
||||
struct pcb;
|
||||
struct thread;
|
||||
extern int (*hmi_handler)(struct trapframe *);
|
||||
void trap(struct trapframe *);
|
||||
int ppc_instr_emulate(struct trapframe *, struct pcb *);
|
||||
int ppc_instr_emulate(struct trapframe *, struct thread *);
|
||||
#endif
|
||||
|
||||
#endif /* _POWERPC_TRAP_H_ */
|
||||
|
@ -1081,8 +1081,9 @@ emulate_mtspr(int spr, int reg, struct trapframe *frame){
|
||||
|
||||
#define XFX 0xFC0007FF
|
||||
int
|
||||
ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
|
||||
ppc_instr_emulate(struct trapframe *frame, struct thread *td)
|
||||
{
|
||||
struct pcb *pcb;
|
||||
uint32_t instr;
|
||||
int reg, sig;
|
||||
int rs, spr;
|
||||
@ -1109,12 +1110,16 @@ ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
|
||||
return (0);
|
||||
}
|
||||
|
||||
pcb = td->td_pcb;
|
||||
#ifdef FPU_EMU
|
||||
if (!(pcb->pcb_flags & PCB_FPREGS)) {
|
||||
bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu));
|
||||
pcb->pcb_flags |= PCB_FPREGS;
|
||||
}
|
||||
} else if (pcb->pcb_flags & PCB_FPU)
|
||||
save_fpu(td);
|
||||
sig = fpu_emulate(frame, &pcb->pcb_fpu);
|
||||
if ((sig == 0 || sig == SIGFPE) && pcb->pcb_flags & PCB_FPU)
|
||||
enable_fpu(td);
|
||||
#endif
|
||||
if (sig == SIGILL) {
|
||||
if (pcb->pcb_lastill != frame->srr0) {
|
||||
|
@ -363,7 +363,7 @@ trap(struct trapframe *frame)
|
||||
sig = SIGTRAP;
|
||||
ucode = TRAP_BRKPT;
|
||||
} else {
|
||||
sig = ppc_instr_emulate(frame, td->td_pcb);
|
||||
sig = ppc_instr_emulate(frame, td);
|
||||
if (sig == SIGILL) {
|
||||
if (frame->srr1 & EXC_PGM_PRIV)
|
||||
ucode = ILL_PRVOPC;
|
||||
|
Loading…
x
Reference in New Issue
Block a user