Changeset View
Changeset View
Standalone View
Standalone View
head/sys/powerpc/powerpc/ptrace_machdep.c
Show All 29 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <sys/ptrace.h> | #include <sys/ptrace.h> | ||||
#include <sys/sysent.h> | #include <sys/sysent.h> | ||||
#include <machine/altivec.h> | #include <machine/altivec.h> | ||||
#include <machine/fpu.h> | |||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <machine/md_var.h> | #include <machine/md_var.h> | ||||
#include <machine/pcb.h> | #include <machine/pcb.h> | ||||
int | int | ||||
cpu_ptrace(struct thread *td, int req, void *addr, int data) | cpu_ptrace(struct thread *td, int req, void *addr, int data) | ||||
{ | { | ||||
int error; | int error; | ||||
struct pcb *pcb; | struct pcb *pcb; | ||||
struct vec vec; | struct vec vec; | ||||
uint64_t vsr[32]; | |||||
uint64_t *vsr_dw1; | |||||
int vsr_idx; | |||||
pcb = td->td_pcb; | pcb = td->td_pcb; | ||||
bzero(&vec, sizeof(vec)); | bzero(&vec, sizeof(vec)); | ||||
bzero(vsr, sizeof(vsr)); | |||||
error = EINVAL; | error = EINVAL; | ||||
switch (req) { | switch (req) { | ||||
case PT_GETVRREGS: | case PT_GETVRREGS: | ||||
if (!(cpu_features & PPC_FEATURE_HAS_ALTIVEC)) | if (!(cpu_features & PPC_FEATURE_HAS_ALTIVEC)) | ||||
break; | break; | ||||
if (pcb->pcb_flags & PCB_VEC) { | if (pcb->pcb_flags & PCB_VEC) { | ||||
save_vec_nodrop(td); | save_vec_nodrop(td); | ||||
memcpy(&vec, &pcb->pcb_vec, sizeof(vec)); | memcpy(&vec, &pcb->pcb_vec, sizeof(vec)); | ||||
} | } | ||||
error = copyout(&vec, addr, sizeof(vec)); | error = copyout(&vec, addr, sizeof(vec)); | ||||
break; | break; | ||||
case PT_SETVRREGS: | case PT_SETVRREGS: | ||||
if (!(cpu_features & PPC_FEATURE_HAS_ALTIVEC)) | if (!(cpu_features & PPC_FEATURE_HAS_ALTIVEC)) | ||||
break; | break; | ||||
error = copyin(addr, &vec, sizeof(vec)); | error = copyin(addr, &vec, sizeof(vec)); | ||||
if (error == 0) { | if (error == 0) { | ||||
pcb->pcb_flags |= PCB_VEC; | pcb->pcb_flags |= PCB_VEC; | ||||
memcpy(&pcb->pcb_vec, &vec, sizeof(vec)); | memcpy(&pcb->pcb_vec, &vec, sizeof(vec)); | ||||
} | |||||
break; | |||||
case PT_GETVSRREGS: | |||||
if (!(cpu_features & PPC_FEATURE_HAS_VSX)) | |||||
break; | |||||
if (pcb->pcb_flags & PCB_VSX) { | |||||
save_fpu_nodrop(td); | |||||
/* | |||||
* Doubleword 0 of VSR0-VSR31 overlap with FPR0-FPR31 and | |||||
* VSR32-VSR63 overlap with VR0-VR31, so we only copy | |||||
* the non-overlapping data, which is doubleword 1 of VSR0-VSR31. | |||||
*/ | |||||
for (vsr_idx = 0; vsr_idx < nitems(vsr); vsr_idx++) { | |||||
vsr_dw1 = (uint64_t *)&pcb->pcb_fpu.fpr[vsr_idx].vsr[2]; | |||||
vsr[vsr_idx] = *vsr_dw1; | |||||
} | |||||
} | |||||
error = copyout(&vsr, addr, sizeof(vsr)); | |||||
break; | |||||
case PT_SETVSRREGS: | |||||
if (!(cpu_features & PPC_FEATURE_HAS_VSX)) | |||||
break; | |||||
error = copyin(addr, &vsr, sizeof(vsr)); | |||||
if (error == 0) { | |||||
pcb->pcb_flags |= PCB_VSX; | |||||
/* | |||||
* Doubleword 0 of VSR0-VSR31 overlap with FPR0-FPR31 and | |||||
* VSR32-VSR63 overlap with VR0-VR31, so we only copy | |||||
* the non-overlapping data, which is doubleword 1 of VSR0-VSR31. | |||||
*/ | |||||
for (vsr_idx = 0; vsr_idx < nitems(vsr); vsr_idx++) { | |||||
vsr_dw1 = (uint64_t *)&pcb->pcb_fpu.fpr[vsr_idx].vsr[2]; | |||||
*vsr_dw1 = vsr[vsr_idx]; | |||||
} | |||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
return (error); | return (error); | ||||
} | } |