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 --- |