Index: head/sys/powerpc/powerpc/elf32_machdep.c =================================================================== --- head/sys/powerpc/powerpc/elf32_machdep.c +++ head/sys/powerpc/powerpc/elf32_machdep.c @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -171,19 +172,44 @@ { size_t len; struct pcb *pcb; + uint64_t vshr[32]; + uint64_t *vsr_dw1; + int vsr_idx; len = 0; pcb = td->td_pcb; + if (pcb->pcb_flags & PCB_VEC) { save_vec_nodrop(td); if (dst != NULL) { len += elf32_populate_note(NT_PPC_VMX, - &pcb->pcb_vec, dst, + &pcb->pcb_vec, (char *)dst + len, sizeof(pcb->pcb_vec), NULL); } else len += elf32_populate_note(NT_PPC_VMX, NULL, NULL, sizeof(pcb->pcb_vec), NULL); } + + if (pcb->pcb_flags & PCB_VSX) { + save_fpu_nodrop(td); + if (dst != NULL) { + /* + * 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(vshr); vsr_idx++) { + vsr_dw1 = (uint64_t *)&pcb->pcb_fpu.fpr[vsr_idx].vsr[2]; + vshr[vsr_idx] = *vsr_dw1; + } + len += elf32_populate_note(NT_PPC_VSX, + vshr, (char *)dst + len, + sizeof(vshr), NULL); + } else + len += elf32_populate_note(NT_PPC_VSX, NULL, NULL, + sizeof(vshr), NULL); + } + *off = len; } Index: head/sys/powerpc/powerpc/elf64_machdep.c =================================================================== --- head/sys/powerpc/powerpc/elf64_machdep.c +++ head/sys/powerpc/powerpc/elf64_machdep.c @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -234,19 +235,44 @@ { size_t len; struct pcb *pcb; + uint64_t vshr[32]; + uint64_t *vsr_dw1; + int vsr_idx; len = 0; pcb = td->td_pcb; + if (pcb->pcb_flags & PCB_VEC) { save_vec_nodrop(td); if (dst != NULL) { len += elf64_populate_note(NT_PPC_VMX, - &pcb->pcb_vec, dst, + &pcb->pcb_vec, (char *)dst + len, sizeof(pcb->pcb_vec), NULL); } else len += elf64_populate_note(NT_PPC_VMX, NULL, NULL, sizeof(pcb->pcb_vec), NULL); } + + if (pcb->pcb_flags & PCB_VSX) { + save_fpu_nodrop(td); + if (dst != NULL) { + /* + * 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(vshr); vsr_idx++) { + vsr_dw1 = (uint64_t *)&pcb->pcb_fpu.fpr[vsr_idx].vsr[2]; + vshr[vsr_idx] = *vsr_dw1; + } + len += elf64_populate_note(NT_PPC_VSX, + vshr, (char *)dst + len, + sizeof(vshr), NULL); + } else + len += elf64_populate_note(NT_PPC_VSX, NULL, NULL, + sizeof(vshr), NULL); + } + *off = len; } Index: head/sys/sys/elf_common.h =================================================================== --- head/sys/sys/elf_common.h +++ head/sys/sys/elf_common.h @@ -774,6 +774,7 @@ #define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */ #define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */ #define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ +#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ #define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */ #define NT_ARM_VFP 0x400 /* ARM VFP registers */ Index: head/usr.bin/gcore/elfcore.c =================================================================== --- head/usr.bin/gcore/elfcore.c +++ head/usr.bin/gcore/elfcore.c @@ -119,6 +119,7 @@ #endif #if defined(__powerpc__) static void *elf_note_powerpc_vmx(void *, size_t *); +static void *elf_note_powerpc_vsx(void *, size_t *); #endif static void *elf_note_procstat_auxv(void *, size_t *); static void *elf_note_procstat_files(void *, size_t *); @@ -381,6 +382,7 @@ #endif #if defined(__powerpc__) elf_putnote(NT_PPC_VMX, elf_note_powerpc_vmx, tids + i, sb); + elf_putnote(NT_PPC_VSX, elf_note_powerpc_vsx, tids + i, sb); #endif } @@ -802,6 +804,30 @@ memcpy(vmx, &info, sizeof(*vmx)); *sizep = sizeof(*vmx); return (vmx); +} + +static void * +elf_note_powerpc_vsx(void *arg, size_t *sizep) +{ + lwpid_t tid; + char *vshr_data; + static bool has_vsx = true; + uint64_t vshr[32]; + + tid = *(lwpid_t *)arg; + if (has_vsx) { + if (ptrace(PT_GETVSRREGS, tid, (void *)vshr, + sizeof(vshr)) != 0) + has_vsx = false; + } + if (!has_vsx) { + *sizep = 0; + return (NULL); + } + vshr_data = calloc(1, sizeof(vshr)); + memcpy(vshr_data, vshr, sizeof(vshr)); + *sizep = sizeof(vshr); + return (vshr_data); } #endif