Changeset View
Changeset View
Standalone View
Standalone View
head/sys/powerpc/powerpc/fpu.c
Show All 39 Lines | |||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/limits.h> | #include <sys/limits.h> | ||||
#include <machine/fpu.h> | #include <machine/fpu.h> | ||||
#include <machine/pcb.h> | #include <machine/pcb.h> | ||||
#include <machine/psl.h> | #include <machine/psl.h> | ||||
static void | |||||
save_fpu_int(struct thread *td) | |||||
{ | |||||
int msr; | |||||
struct pcb *pcb; | |||||
pcb = td->td_pcb; | |||||
/* | |||||
* Temporarily re-enable floating-point during the save | |||||
*/ | |||||
msr = mfmsr(); | |||||
if (pcb->pcb_flags & PCB_VSX) | |||||
mtmsr(msr | PSL_FP | PSL_VSX); | |||||
else | |||||
mtmsr(msr | PSL_FP); | |||||
/* | |||||
* Save the floating-point registers and FPSCR to the PCB | |||||
*/ | |||||
if (pcb->pcb_flags & PCB_VSX) { | |||||
#define SFP(n) __asm ("stxvw4x " #n ", 0,%0" \ | |||||
:: "b"(&pcb->pcb_fpu.fpr[n])); | |||||
SFP(0); SFP(1); SFP(2); SFP(3); | |||||
SFP(4); SFP(5); SFP(6); SFP(7); | |||||
SFP(8); SFP(9); SFP(10); SFP(11); | |||||
SFP(12); SFP(13); SFP(14); SFP(15); | |||||
SFP(16); SFP(17); SFP(18); SFP(19); | |||||
SFP(20); SFP(21); SFP(22); SFP(23); | |||||
SFP(24); SFP(25); SFP(26); SFP(27); | |||||
SFP(28); SFP(29); SFP(30); SFP(31); | |||||
#undef SFP | |||||
} else { | |||||
#define SFP(n) __asm ("stfd " #n ", 0(%0)" \ | |||||
:: "b"(&pcb->pcb_fpu.fpr[n])); | |||||
SFP(0); SFP(1); SFP(2); SFP(3); | |||||
SFP(4); SFP(5); SFP(6); SFP(7); | |||||
SFP(8); SFP(9); SFP(10); SFP(11); | |||||
SFP(12); SFP(13); SFP(14); SFP(15); | |||||
SFP(16); SFP(17); SFP(18); SFP(19); | |||||
SFP(20); SFP(21); SFP(22); SFP(23); | |||||
SFP(24); SFP(25); SFP(26); SFP(27); | |||||
SFP(28); SFP(29); SFP(30); SFP(31); | |||||
#undef SFP | |||||
} | |||||
__asm __volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); | |||||
/* | |||||
* Disable floating-point again | |||||
*/ | |||||
isync(); | |||||
mtmsr(msr); | |||||
} | |||||
void | void | ||||
enable_fpu(struct thread *td) | enable_fpu(struct thread *td) | ||||
{ | { | ||||
int msr; | int msr; | ||||
struct pcb *pcb; | struct pcb *pcb; | ||||
struct trapframe *tf; | struct trapframe *tf; | ||||
pcb = td->td_pcb; | pcb = td->td_pcb; | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | enable_fpu(struct thread *td) | ||||
isync(); | isync(); | ||||
mtmsr(msr); | mtmsr(msr); | ||||
} | } | ||||
void | void | ||||
save_fpu(struct thread *td) | save_fpu(struct thread *td) | ||||
{ | { | ||||
int msr; | |||||
struct pcb *pcb; | struct pcb *pcb; | ||||
pcb = td->td_pcb; | pcb = td->td_pcb; | ||||
/* | save_fpu_int(td); | ||||
* Temporarily re-enable floating-point during the save | |||||
*/ | |||||
msr = mfmsr(); | |||||
if (pcb->pcb_flags & PCB_VSX) | |||||
mtmsr(msr | PSL_FP | PSL_VSX); | |||||
else | |||||
mtmsr(msr | PSL_FP); | |||||
/* | /* | ||||
* Save the floating-point registers and FPSCR to the PCB | * Clear the current fp thread and pcb's CPU id | ||||
* XXX should this be left clear to allow lazy save/restore ? | |||||
*/ | */ | ||||
if (pcb->pcb_flags & PCB_VSX) { | pcb->pcb_fpcpu = INT_MAX; | ||||
#define SFP(n) __asm ("stxvw4x " #n ", 0,%0" \ | PCPU_SET(fputhread, NULL); | ||||
:: "b"(&pcb->pcb_fpu.fpr[n])); | |||||
SFP(0); SFP(1); SFP(2); SFP(3); | |||||
SFP(4); SFP(5); SFP(6); SFP(7); | |||||
SFP(8); SFP(9); SFP(10); SFP(11); | |||||
SFP(12); SFP(13); SFP(14); SFP(15); | |||||
SFP(16); SFP(17); SFP(18); SFP(19); | |||||
SFP(20); SFP(21); SFP(22); SFP(23); | |||||
SFP(24); SFP(25); SFP(26); SFP(27); | |||||
SFP(28); SFP(29); SFP(30); SFP(31); | |||||
#undef SFP | |||||
} else { | |||||
#define SFP(n) __asm ("stfd " #n ", 0(%0)" \ | |||||
:: "b"(&pcb->pcb_fpu.fpr[n])); | |||||
SFP(0); SFP(1); SFP(2); SFP(3); | |||||
SFP(4); SFP(5); SFP(6); SFP(7); | |||||
SFP(8); SFP(9); SFP(10); SFP(11); | |||||
SFP(12); SFP(13); SFP(14); SFP(15); | |||||
SFP(16); SFP(17); SFP(18); SFP(19); | |||||
SFP(20); SFP(21); SFP(22); SFP(23); | |||||
SFP(24); SFP(25); SFP(26); SFP(27); | |||||
SFP(28); SFP(29); SFP(30); SFP(31); | |||||
#undef SFP | |||||
} | } | ||||
__asm __volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); | |||||
/* | /* | ||||
* Disable floating-point again | * Save fpu state without dropping ownership. This will only save state if | ||||
* the current fpu thread is `td'. | |||||
*/ | */ | ||||
isync(); | void | ||||
mtmsr(msr); | save_fpu_nodrop(struct thread *td) | ||||
{ | |||||
struct thread *ftd; | |||||
/* | ftd = PCPU_GET(fputhread); | ||||
* Clear the current fp thread and pcb's CPU id | if (td != ftd) { | ||||
* XXX should this be left clear to allow lazy save/restore ? | return; | ||||
*/ | |||||
pcb->pcb_fpcpu = INT_MAX; | |||||
PCPU_SET(fputhread, NULL); | |||||
} | } | ||||
save_fpu_int(td); | |||||
} |