Deleted Added
full compact
1/*-
2 * Copyright (c) 1990 William Jolitz.
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 17 unchanged lines hidden (view full) ---

26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * from: @(#)npx.c 7.2 (Berkeley) 5/12/91
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/amd64/amd64/fpu.c 238597 2012-07-18 15:36:03Z kib $");
34__FBSDID("$FreeBSD: head/sys/amd64/amd64/fpu.c 238598 2012-07-18 15:43:47Z kib $");
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/bus.h>
39#include <sys/kernel.h>
40#include <sys/lock.h>
41#include <sys/malloc.h>
42#include <sys/module.h>

--- 67 unchanged lines hidden (view full) ---

110void xrstor(char *addr, uint64_t mask);
111void xsave(char *addr, uint64_t mask);
112
113#endif /* __GNUCLIKE_ASM && !lint */
114
115#define start_emulating() load_cr0(rcr0() | CR0_TS)
116#define stop_emulating() clts()
117
118#define GET_FPU_CW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_cw)
119#define GET_FPU_SW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_sw)
120
118CTASSERT(sizeof(struct savefpu) == 512);
119CTASSERT(sizeof(struct xstate_hdr) == 64);
120CTASSERT(sizeof(struct savefpu_ymm) == 832);
121
122/*
123 * This requirement is to make it easier for asm code to calculate
124 * offset of the fpu save area from the pcb address. FPU save area
125 * must be 64-byte aligned.

--- 382 unchanged lines hidden (view full) ---

508 FPE_FLTSUB, /* 7B - INV | DNML | OFL | UFL | IMP | STK */
509 FPE_FLTDIV, /* 7C - DZ | OFL | UFL | IMP | STK */
510 FPE_FLTSUB, /* 7D - INV | DZ | OFL | UFL | IMP | STK */
511 FPE_FLTDIV, /* 7E - DNML | DZ | OFL | UFL | IMP | STK */
512 FPE_FLTSUB, /* 7F - INV | DNML | DZ | OFL | UFL | IMP | STK */
513};
514
515/*
519 * Preserve the FP status word, clear FP exceptions, then generate a SIGFPE.
516 * Preserve the FP status word, clear FP exceptions for x87, then
517 * generate a SIGFPE.
518 *
521 * Clearing exceptions is necessary mainly to avoid IRQ13 bugs. We now
522 * depend on longjmp() restoring a usable state. Restoring the state
523 * or examining it might fail if we didn't clear exceptions.
519 * Clearing exceptions was necessary mainly to avoid IRQ13 bugs and is
520 * engraved in our i386 ABI. We now depend on longjmp() restoring a
521 * usable state. Restoring the state or examining it might fail if we
522 * didn't clear exceptions.
523 *
524 * For SSE exceptions, the exceptions are not cleared.
525 *
526 * The error code chosen will be one of the FPE_... macros. It will be
527 * sent as the second argument to old BSD-style signal handlers and as
528 * "siginfo_t->si_code" (second argument) to SA_SIGINFO signal handlers.
529 *
530 * XXX the FP state is not preserved across signal handlers. So signal
531 * handlers cannot afford to do FP unless they preserve the state or
532 * longjmp() out. Both preserving the state and longjmp()ing may be
533 * destroyed by IRQ13 bugs. Clearing FP exceptions is not an acceptable
534 * solution for signals other than SIGFPE.
535 */
536int
536fputrap()
537fputrap_x87(void)
538{
539 struct savefpu *pcb_save;
540 u_short control, status;
541
542 critical_enter();
543
544 /*
545 * Interrupt handling (for another interrupt) may have pushed the
546 * state to memory. Fetch the relevant parts of the state from
547 * wherever they are.
548 */
549 if (PCPU_GET(fpcurthread) != curthread) {
548 control = GET_FPU_CW(curthread);
549 status = GET_FPU_SW(curthread);
550 pcb_save = PCPU_GET(curpcb)->pcb_save;
551 control = pcb_save->sv_env.en_cw;
552 status = pcb_save->sv_env.en_sw;
553 } else {
554 fnstcw(&control);
555 fnstsw(&status);
556 fnclex();
557 }
558
555 if (PCPU_GET(fpcurthread) == curthread)
556 fnclex();
559 critical_exit();
560 return (fpetable[status & ((~control & 0x3f) | 0x40)]);
561}
562
563int
564fputrap_sse(void)
565{
566 u_int mxcsr;
567
568 critical_enter();
569 if (PCPU_GET(fpcurthread) != curthread)
570 mxcsr = PCPU_GET(curpcb)->pcb_save->sv_env.en_mxcsr;
571 else
572 stmxcsr(&mxcsr);
573 critical_exit();
574 return (fpetable[(mxcsr & (~mxcsr >> 7)) & 0x3f]);
575}
576
577/*
578 * Implement device not available (DNA) exception
579 *
580 * It would be better to switch FP context here (if curthread != fpcurthread)
581 * and not necessarily for every context switch, but it is too hard to
582 * access foreign pcb's.
583 */
584

--- 407 unchanged lines hidden ---