powerpc: Sync icache on SIGILL, in case of cache issues
The update of jemalloc to 5.1.0 exposed a cache syncing issue on a Freescale e500 base system. There was already code in the FPU emulator to address this, but it was limited to a single static variable, and did not attempt to sync the cache. This pulls that out to the higher level program exception handler, and syncs the cache. If a SIGILL is hit a second time at the same address, it will be treated as a real illegal instruction, and handled accordingly.
This commit is contained in:
parent
06cf1308e4
commit
fe5e88fabf
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=340653
@ -189,7 +189,6 @@ fpu_emulate(struct trapframe *frame, struct fpu *fpf)
|
||||
{
|
||||
union instr insn;
|
||||
struct fpemu fe;
|
||||
static int lastill = 0;
|
||||
int sig;
|
||||
|
||||
/* initialize insn.is_datasize to tell it is *not* initialized */
|
||||
@ -243,17 +242,11 @@ fpu_emulate(struct trapframe *frame, struct fpu *fpf)
|
||||
opc_disasm(frame->srr0, insn.i_int);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* XXXX retry an illegal insn once due to cache issues.
|
||||
*/
|
||||
if (lastill == frame->srr0) {
|
||||
sig = SIGILL;
|
||||
sig = SIGILL;
|
||||
#ifdef DEBUG
|
||||
if (fpe_debug & FPE_EX)
|
||||
kdb_enter(KDB_WHY_UNSET, "illegal instruction");
|
||||
if (fpe_debug & FPE_EX)
|
||||
kdb_enter(KDB_WHY_UNSET, "illegal instruction");
|
||||
#endif
|
||||
}
|
||||
lastill = frame->srr0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -89,6 +89,7 @@ struct pcb {
|
||||
register_t dbcr0;
|
||||
} booke;
|
||||
} pcb_cpu;
|
||||
vm_offset_t pcb_lastill; /* Last illegal instruction */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -94,6 +94,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/trap.h>
|
||||
#include <machine/vmparam.h>
|
||||
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#ifdef FPU_EMU
|
||||
#include <powerpc/fpu/fpu_extern.h>
|
||||
#endif
|
||||
@ -1099,6 +1101,14 @@ ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb)
|
||||
}
|
||||
sig = fpu_emulate(frame, &pcb->pcb_fpu);
|
||||
#endif
|
||||
if (sig == SIGILL) {
|
||||
if (pcb->pcb_lastill != frame->srr0) {
|
||||
/* Allow a second chance, in case of cache sync issues. */
|
||||
sig = 0;
|
||||
pmap_sync_icache(PCPU_GET(curpmap), frame->srr0, 4);
|
||||
pcb->pcb_lastill = frame->srr0;
|
||||
}
|
||||
}
|
||||
|
||||
return (sig);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user