From fe5e88fabf5fdef582b0e5b4edff339e163a51f8 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Mon, 19 Nov 2018 23:54:49 +0000 Subject: [PATCH] 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. --- sys/powerpc/fpu/fpu_emu.c | 13 +++---------- sys/powerpc/include/pcb.h | 1 + sys/powerpc/powerpc/exec_machdep.c | 10 ++++++++++ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/sys/powerpc/fpu/fpu_emu.c b/sys/powerpc/fpu/fpu_emu.c index 75f44c7b786a..4d7231e5da93 100644 --- a/sys/powerpc/fpu/fpu_emu.c +++ b/sys/powerpc/fpu/fpu_emu.c @@ -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; } diff --git a/sys/powerpc/include/pcb.h b/sys/powerpc/include/pcb.h index 451b730225ca..df0e2ff6951b 100644 --- a/sys/powerpc/include/pcb.h +++ b/sys/powerpc/include/pcb.h @@ -89,6 +89,7 @@ struct pcb { register_t dbcr0; } booke; } pcb_cpu; + vm_offset_t pcb_lastill; /* Last illegal instruction */ }; #endif diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index 18ff66f26f3f..718962ffcb6f 100644 --- a/sys/powerpc/powerpc/exec_machdep.c +++ b/sys/powerpc/powerpc/exec_machdep.c @@ -94,6 +94,8 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #ifdef FPU_EMU #include #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); }