diff options
author | jhb <jhb@FreeBSD.org> | 2016-02-01 23:12:04 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2016-02-01 23:12:04 +0000 |
commit | 0e26efe2d7cf6ba3520c373445f73eca41063634 (patch) | |
tree | b4cc30e17f8aa862ea6005df019e28fa263b8435 /sys/powerpc/powerpc | |
parent | 0924d1687c5bc1e7e372986f9ec31e50ccd21c7b (diff) | |
download | FreeBSD-src-0e26efe2d7cf6ba3520c373445f73eca41063634.zip FreeBSD-src-0e26efe2d7cf6ba3520c373445f73eca41063634.tar.gz |
Restore the ABI of 'struct fpreg' on powerpc.
The PT_{GET,SET}FPREGS requests use 'struct fpreg' and the NT_FPREGSET
core note stores a copy of 'struct fpreg'. As with x86 and the floating
point state there compared to the extended state in XSAVE, struct fpreg
on powerpc now only holds the 'base' FP state, and setting it via
PT_SETFPREGS leaves the extended vector state in a thread unchanged.
Reviewed by: jhibbits
Differential Revision: https://reviews.freebsd.org/D5004
Diffstat (limited to 'sys/powerpc/powerpc')
-rw-r--r-- | sys/powerpc/powerpc/exec_machdep.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index d657244f..d8238a1 100644 --- a/sys/powerpc/powerpc/exec_machdep.c +++ b/sys/powerpc/powerpc/exec_machdep.c @@ -608,13 +608,18 @@ int fill_fpregs(struct thread *td, struct fpreg *fpregs) { struct pcb *pcb; + int i; pcb = td->td_pcb; if ((pcb->pcb_flags & PCB_FPREGS) == 0) memset(fpregs, 0, sizeof(struct fpreg)); - else - memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg)); + else { + memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); + for (i = 0; i < 32; i++) + memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr, + sizeof(double)); + } return (0); } @@ -641,10 +646,15 @@ int set_fpregs(struct thread *td, struct fpreg *fpregs) { struct pcb *pcb; + int i; pcb = td->td_pcb; pcb->pcb_flags |= PCB_FPREGS; - memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg)); + memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double)); + for (i = 0; i < 32; i++) { + memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i], + sizeof(double)); + } return (0); } @@ -1060,7 +1070,7 @@ ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb) bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu)); pcb->pcb_flags |= PCB_FPREGS; } - sig = fpu_emulate(frame, (struct fpreg *)&pcb->pcb_fpu); + sig = fpu_emulate(frame, &pcb->pcb_fpu); #endif return (sig); |