Deleted Added
full compact
fpu.c (238597) fpu.c (238598)
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>
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
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
121CTASSERT(sizeof(struct savefpu) == 512);
122CTASSERT(sizeof(struct xstate_hdr) == 64);
123CTASSERT(sizeof(struct savefpu_ymm) == 832);
124
125/*
126 * This requirement is to make it easier for asm code to calculate
127 * offset of the fpu save area from the pcb address. FPU save area
128 * must be 64-byte aligned.

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

511 FPE_FLTSUB, /* 7B - INV | DNML | OFL | UFL | IMP | STK */
512 FPE_FLTDIV, /* 7C - DZ | OFL | UFL | IMP | STK */
513 FPE_FLTSUB, /* 7D - INV | DZ | OFL | UFL | IMP | STK */
514 FPE_FLTDIV, /* 7E - DNML | DZ | OFL | UFL | IMP | STK */
515 FPE_FLTSUB, /* 7F - INV | DNML | DZ | OFL | UFL | IMP | STK */
516};
517
518/*
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.
520 *
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.
524 *
523 *
524 * For SSE exceptions, the exceptions are not cleared.
525 *
525 * The error code chosen will be one of the FPE_... macros. It will be
526 * sent as the second argument to old BSD-style signal handlers and as
527 * "siginfo_t->si_code" (second argument) to SA_SIGINFO signal handlers.
528 *
529 * XXX the FP state is not preserved across signal handlers. So signal
530 * handlers cannot afford to do FP unless they preserve the state or
531 * longjmp() out. Both preserving the state and longjmp()ing may be
532 * destroyed by IRQ13 bugs. Clearing FP exceptions is not an acceptable
533 * solution for signals other than SIGFPE.
534 */
535int
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)
537{
538{
539 struct savefpu *pcb_save;
538 u_short control, status;
539
540 critical_enter();
541
542 /*
543 * Interrupt handling (for another interrupt) may have pushed the
544 * state to memory. Fetch the relevant parts of the state from
545 * wherever they are.
546 */
547 if (PCPU_GET(fpcurthread) != curthread) {
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;
550 } else {
551 fnstcw(&control);
552 fnstsw(&status);
553 } else {
554 fnstcw(&control);
555 fnstsw(&status);
556 fnclex();
553 }
554
557 }
558
555 if (PCPU_GET(fpcurthread) == curthread)
556 fnclex();
557 critical_exit();
558 return (fpetable[status & ((~control & 0x3f) | 0x40)]);
559}
560
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
561/*
562 * Implement device not available (DNA) exception
563 *
564 * It would be better to switch FP context here (if curthread != fpcurthread)
565 * and not necessarily for every context switch, but it is too hard to
566 * access foreign pcb's.
567 */
568

--- 407 unchanged lines hidden ---
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 ---