Deleted Added
full compact
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 ---