mirror of
https://github.com/opnsense/src.git
synced 2026-04-21 06:07:31 -04:00
On AMD64, provide siginfo.si_code for floating point errors when error
occurs using the SSE math processor. Update comments describing the handling of the exception status bits in coprocessors control words. Remove GET_FPU_CW and GET_FPU_SW macros which were used only once. Prefer to use curpcb to access pcb_save over the longer path of referencing pcb through the thread structure. Based on the submission by: Ed Alley <wea llnl gov> PR: amd64/169927 Reviewed by: bde MFC after: 3 weeks
This commit is contained in:
parent
a81f9fed5d
commit
bc84db6267
3 changed files with 34 additions and 15 deletions
|
|
@ -115,9 +115,6 @@ void xsave(char *addr, uint64_t mask);
|
|||
#define start_emulating() load_cr0(rcr0() | CR0_TS)
|
||||
#define stop_emulating() clts()
|
||||
|
||||
#define GET_FPU_CW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_cw)
|
||||
#define GET_FPU_SW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_sw)
|
||||
|
||||
CTASSERT(sizeof(struct savefpu) == 512);
|
||||
CTASSERT(sizeof(struct xstate_hdr) == 64);
|
||||
CTASSERT(sizeof(struct savefpu_ymm) == 832);
|
||||
|
|
@ -516,11 +513,15 @@ static char fpetable[128] = {
|
|||
};
|
||||
|
||||
/*
|
||||
* Preserve the FP status word, clear FP exceptions, then generate a SIGFPE.
|
||||
* Preserve the FP status word, clear FP exceptions for x87, then
|
||||
* generate a SIGFPE.
|
||||
*
|
||||
* Clearing exceptions is necessary mainly to avoid IRQ13 bugs. We now
|
||||
* depend on longjmp() restoring a usable state. Restoring the state
|
||||
* or examining it might fail if we didn't clear exceptions.
|
||||
* Clearing exceptions was necessary mainly to avoid IRQ13 bugs and is
|
||||
* engraved in our i386 ABI. We now depend on longjmp() restoring a
|
||||
* usable state. Restoring the state or examining it might fail if we
|
||||
* didn't clear exceptions.
|
||||
*
|
||||
* For SSE exceptions, the exceptions are not cleared.
|
||||
*
|
||||
* The error code chosen will be one of the FPE_... macros. It will be
|
||||
* sent as the second argument to old BSD-style signal handlers and as
|
||||
|
|
@ -533,8 +534,9 @@ static char fpetable[128] = {
|
|||
* solution for signals other than SIGFPE.
|
||||
*/
|
||||
int
|
||||
fputrap()
|
||||
fputrap_x87(void)
|
||||
{
|
||||
struct savefpu *pcb_save;
|
||||
u_short control, status;
|
||||
|
||||
critical_enter();
|
||||
|
|
@ -545,19 +547,33 @@ fputrap()
|
|||
* wherever they are.
|
||||
*/
|
||||
if (PCPU_GET(fpcurthread) != curthread) {
|
||||
control = GET_FPU_CW(curthread);
|
||||
status = GET_FPU_SW(curthread);
|
||||
pcb_save = PCPU_GET(curpcb)->pcb_save;
|
||||
control = pcb_save->sv_env.en_cw;
|
||||
status = pcb_save->sv_env.en_sw;
|
||||
} else {
|
||||
fnstcw(&control);
|
||||
fnstsw(&status);
|
||||
fnclex();
|
||||
}
|
||||
|
||||
if (PCPU_GET(fpcurthread) == curthread)
|
||||
fnclex();
|
||||
critical_exit();
|
||||
return (fpetable[status & ((~control & 0x3f) | 0x40)]);
|
||||
}
|
||||
|
||||
int
|
||||
fputrap_sse(void)
|
||||
{
|
||||
u_int mxcsr;
|
||||
|
||||
critical_enter();
|
||||
if (PCPU_GET(fpcurthread) != curthread)
|
||||
mxcsr = PCPU_GET(curpcb)->pcb_save->sv_env.en_mxcsr;
|
||||
else
|
||||
stmxcsr(&mxcsr);
|
||||
critical_exit();
|
||||
return (fpetable[(mxcsr & (~mxcsr >> 7)) & 0x3f]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement device not available (DNA) exception
|
||||
*
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ trap(struct trapframe *frame)
|
|||
break;
|
||||
|
||||
case T_ARITHTRAP: /* arithmetic trap */
|
||||
ucode = fputrap();
|
||||
ucode = fputrap_x87();
|
||||
if (ucode == -1)
|
||||
goto userout;
|
||||
i = SIGFPE;
|
||||
|
|
@ -442,7 +442,9 @@ trap(struct trapframe *frame)
|
|||
break;
|
||||
|
||||
case T_XMMFLT: /* SIMD floating-point exception */
|
||||
ucode = 0; /* XXX */
|
||||
ucode = fputrap_sse();
|
||||
if (ucode == -1)
|
||||
goto userout;
|
||||
i = SIGFPE;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,8 @@ int fpusetregs(struct thread *td, struct savefpu *addr,
|
|||
char *xfpustate, size_t xfpustate_size);
|
||||
int fpusetxstate(struct thread *td, char *xfpustate,
|
||||
size_t xfpustate_size);
|
||||
int fputrap(void);
|
||||
int fputrap_sse(void);
|
||||
int fputrap_x87(void);
|
||||
void fpuuserinited(struct thread *td);
|
||||
struct fpu_kern_ctx *fpu_kern_alloc_ctx(u_int flags);
|
||||
void fpu_kern_free_ctx(struct fpu_kern_ctx *ctx);
|
||||
|
|
|
|||
Loading…
Reference in a new issue