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 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 |
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/* |
516 * Preserve the FP status word, clear FP exceptions for x87, then 517 * generate a SIGFPE. |
518 * |
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 |
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) { |
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 |
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 --- |