fpu.c (215845) | fpu.c (215865) |
---|---|
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 215845 2010-11-25 22:19:40Z dim $"); | 34__FBSDID("$FreeBSD: head/sys/amd64/amd64/fpu.c 215865 2010-11-26 14:50:42Z 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> --- 378 unchanged lines hidden (view full) --- 421 /* 422 * This is the first time this thread has used the FPU or 423 * the PCB doesn't contain a clean FPU state. Explicitly 424 * load an initial state. 425 */ 426 fxrstor(&fpu_initialstate); 427 if (pcb->pcb_initial_fpucw != __INITIAL_FPUCW__) 428 fldcw(pcb->pcb_initial_fpucw); | 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> --- 378 unchanged lines hidden (view full) --- 421 /* 422 * This is the first time this thread has used the FPU or 423 * the PCB doesn't contain a clean FPU state. Explicitly 424 * load an initial state. 425 */ 426 fxrstor(&fpu_initialstate); 427 if (pcb->pcb_initial_fpucw != __INITIAL_FPUCW__) 428 fldcw(pcb->pcb_initial_fpucw); |
429 pcb->pcb_flags |= PCB_FPUINITDONE; 430 if (PCB_USER_FPU(pcb)) 431 pcb->pcb_flags |= PCB_USERFPUINITDONE; | 429 fpuuserinited(curthread); |
432 } else 433 fxrstor(pcb->pcb_save); 434 critical_exit(); 435} 436 437void 438fpudrop() 439{ 440 struct thread *td; 441 442 td = PCPU_GET(fpcurthread); 443 KASSERT(td == curthread, ("fpudrop: fpcurthread != curthread")); 444 CRITICAL_ASSERT(td); 445 PCPU_SET(fpcurthread, NULL); 446 td->td_pcb->pcb_flags &= ~PCB_FPUINITDONE; 447 start_emulating(); 448} 449 450/* | 430 } else 431 fxrstor(pcb->pcb_save); 432 critical_exit(); 433} 434 435void 436fpudrop() 437{ 438 struct thread *td; 439 440 td = PCPU_GET(fpcurthread); 441 KASSERT(td == curthread, ("fpudrop: fpcurthread != curthread")); 442 CRITICAL_ASSERT(td); 443 PCPU_SET(fpcurthread, NULL); 444 td->td_pcb->pcb_flags &= ~PCB_FPUINITDONE; 445 start_emulating(); 446} 447 448/* |
451 * Get the state of the FPU without dropping ownership (if possible). 452 * It returns the FPU ownership status. | 449 * Get the user state of the FPU into pcb->pcb_user_save without 450 * dropping ownership (if possible). It returns the FPU ownership 451 * status. |
453 */ 454int | 452 */ 453int |
455fpugetuserregs(struct thread *td, struct savefpu *addr) | 454fpugetregs(struct thread *td) |
456{ 457 struct pcb *pcb; 458 459 pcb = td->td_pcb; 460 if ((pcb->pcb_flags & PCB_USERFPUINITDONE) == 0) { | 455{ 456 struct pcb *pcb; 457 458 pcb = td->td_pcb; 459 if ((pcb->pcb_flags & PCB_USERFPUINITDONE) == 0) { |
461 bcopy(&fpu_initialstate, addr, sizeof(fpu_initialstate)); 462 addr->sv_env.en_cw = pcb->pcb_initial_fpucw; 463 return (_MC_FPOWNED_NONE); | 460 bcopy(&fpu_initialstate, &pcb->pcb_user_save, 461 sizeof(fpu_initialstate)); 462 pcb->pcb_user_save.sv_env.en_cw = pcb->pcb_initial_fpucw; 463 fpuuserinited(td); 464 return (_MC_FPOWNED_PCB); |
464 } 465 critical_enter(); 466 if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) { | 465 } 466 critical_enter(); 467 if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) { |
467 fxsave(addr); | 468 fxsave(&pcb->pcb_user_save); |
468 critical_exit(); 469 return (_MC_FPOWNED_FPU); 470 } else { 471 critical_exit(); | 469 critical_exit(); 470 return (_MC_FPOWNED_FPU); 471 } else { 472 critical_exit(); |
472 bcopy(&pcb->pcb_user_save, addr, sizeof(*addr)); | |
473 return (_MC_FPOWNED_PCB); 474 } 475} 476 | 473 return (_MC_FPOWNED_PCB); 474 } 475} 476 |
477int 478fpugetregs(struct thread *td, struct savefpu *addr) | 477void 478fpuuserinited(struct thread *td) |
479{ 480 struct pcb *pcb; 481 482 pcb = td->td_pcb; | 479{ 480 struct pcb *pcb; 481 482 pcb = td->td_pcb; |
483 if ((pcb->pcb_flags & PCB_FPUINITDONE) == 0) { 484 bcopy(&fpu_initialstate, addr, sizeof(fpu_initialstate)); 485 addr->sv_env.en_cw = pcb->pcb_initial_fpucw; 486 return (_MC_FPOWNED_NONE); 487 } 488 critical_enter(); 489 if (td == PCPU_GET(fpcurthread)) { 490 fxsave(addr); 491 critical_exit(); 492 return (_MC_FPOWNED_FPU); 493 } else { 494 critical_exit(); 495 bcopy(pcb->pcb_save, addr, sizeof(*addr)); 496 return (_MC_FPOWNED_PCB); 497 } | 483 if (PCB_USER_FPU(pcb)) 484 pcb->pcb_flags |= PCB_FPUINITDONE; 485 pcb->pcb_flags |= PCB_USERFPUINITDONE; |
498} 499 500/* 501 * Set the state of the FPU. 502 */ 503void | 486} 487 488/* 489 * Set the state of the FPU. 490 */ 491void |
504fpusetuserregs(struct thread *td, struct savefpu *addr) | 492fpusetregs(struct thread *td, struct savefpu *addr) |
505{ 506 struct pcb *pcb; 507 508 pcb = td->td_pcb; 509 critical_enter(); 510 if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) { 511 fxrstor(addr); 512 critical_exit(); 513 pcb->pcb_flags |= PCB_FPUINITDONE | PCB_USERFPUINITDONE; 514 } else { 515 critical_exit(); 516 bcopy(addr, &td->td_pcb->pcb_user_save, sizeof(*addr)); | 493{ 494 struct pcb *pcb; 495 496 pcb = td->td_pcb; 497 critical_enter(); 498 if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) { 499 fxrstor(addr); 500 critical_exit(); 501 pcb->pcb_flags |= PCB_FPUINITDONE | PCB_USERFPUINITDONE; 502 } else { 503 critical_exit(); 504 bcopy(addr, &td->td_pcb->pcb_user_save, sizeof(*addr)); |
517 if (PCB_USER_FPU(pcb)) 518 pcb->pcb_flags |= PCB_FPUINITDONE; 519 pcb->pcb_flags |= PCB_USERFPUINITDONE; | 505 fpuuserinited(td); |
520 } 521} 522 | 506 } 507} 508 |
523void 524fpusetregs(struct thread *td, struct savefpu *addr) 525{ 526 struct pcb *pcb; 527 528 pcb = td->td_pcb; 529 critical_enter(); 530 if (td == PCPU_GET(fpcurthread)) { 531 fxrstor(addr); 532 critical_exit(); 533 } else { 534 critical_exit(); 535 bcopy(addr, td->td_pcb->pcb_save, sizeof(*addr)); 536 } 537 if (PCB_USER_FPU(pcb)) 538 pcb->pcb_flags |= PCB_USERFPUINITDONE; 539 pcb->pcb_flags |= PCB_FPUINITDONE; 540} 541 | |
542/* 543 * On AuthenticAMD processors, the fxrstor instruction does not restore 544 * the x87's stored last instruction pointer, last data pointer, and last 545 * opcode values, except in the rare case in which the exception summary 546 * (ES) bit in the x87 status word is set to 1. 547 * 548 * In order to avoid leaking this information across processes, we clean 549 * these values by performing a dummy load before executing fxrstor(). --- 148 unchanged lines hidden --- | 509/* 510 * On AuthenticAMD processors, the fxrstor instruction does not restore 511 * the x87's stored last instruction pointer, last data pointer, and last 512 * opcode values, except in the rare case in which the exception summary 513 * (ES) bit in the x87 status word is set to 1. 514 * 515 * In order to avoid leaking this information across processes, we clean 516 * these values by performing a dummy load before executing fxrstor(). --- 148 unchanged lines hidden --- |