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); | ||||
| } | } | ||||