summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
authorjhibbits <jhibbits@FreeBSD.org>2015-01-03 21:06:06 +0000
committerjhibbits <jhibbits@FreeBSD.org>2015-01-03 21:06:06 +0000
commit30f6d6864b33446ee00b262695b3ee1063ae42d4 (patch)
tree17f05ffd579b4ef9355821979387d7f7d95be7ba /sys/powerpc
parent6f10ad7da97c010bc2fa21737cab7b74d214b992 (diff)
downloadFreeBSD-src-30f6d6864b33446ee00b262695b3ee1063ae42d4.zip
FreeBSD-src-30f6d6864b33446ee00b262695b3ee1063ae42d4.tar.gz
Dump VMX registers into the userland coredump.
Reviewed by: nwhitehorn MFC after: 2 weeks
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/include/altivec.h1
-rw-r--r--sys/powerpc/powerpc/altivec.c89
-rw-r--r--sys/powerpc/powerpc/elf32_machdep.c20
-rw-r--r--sys/powerpc/powerpc/elf64_machdep.c20
4 files changed, 95 insertions, 35 deletions
diff --git a/sys/powerpc/include/altivec.h b/sys/powerpc/include/altivec.h
index 9a6c5d3..0b24445 100644
--- a/sys/powerpc/include/altivec.h
+++ b/sys/powerpc/include/altivec.h
@@ -34,6 +34,7 @@
void enable_vec(struct thread *);
void save_vec(struct thread *);
+void save_vec_nodrop(struct thread *);
#endif /* _MACHINE_ALTIVEC_H_ */
diff --git a/sys/powerpc/powerpc/altivec.c b/sys/powerpc/powerpc/altivec.c
index eeec2bb..d1d6f1b 100644
--- a/sys/powerpc/powerpc/altivec.c
+++ b/sys/powerpc/powerpc/altivec.c
@@ -43,6 +43,46 @@ __FBSDID("$FreeBSD$");
#include <machine/pcb.h>
#include <machine/psl.h>
+static void
+save_vec_int(struct thread *td)
+{
+ int msr;
+ struct pcb *pcb;
+
+ pcb = td->td_pcb;
+
+ /*
+ * Temporarily re-enable the vector unit during the save
+ */
+ msr = mfmsr();
+ mtmsr(msr | PSL_VEC);
+ isync();
+
+ /*
+ * Save the vector registers and VSCR to the PCB
+ */
+#define STVX(n) __asm ("stvx %1,0,%0" \
+ :: "b"(pcb->pcb_vec.vr[n]), "n"(n));
+ STVX(0); STVX(1); STVX(2); STVX(3);
+ STVX(4); STVX(5); STVX(6); STVX(7);
+ STVX(8); STVX(9); STVX(10); STVX(11);
+ STVX(12); STVX(13); STVX(14); STVX(15);
+ STVX(16); STVX(17); STVX(18); STVX(19);
+ STVX(20); STVX(21); STVX(22); STVX(23);
+ STVX(24); STVX(25); STVX(26); STVX(27);
+ STVX(28); STVX(29); STVX(30); STVX(31);
+#undef STVX
+
+ __asm __volatile("mfvscr 0; stvewx 0,0,%0" :: "b"(&pcb->pcb_vec.vscr));
+
+ /*
+ * Disable vector unit again
+ */
+ isync();
+ mtmsr(msr);
+
+}
+
void
enable_vec(struct thread *td)
{
@@ -107,40 +147,11 @@ enable_vec(struct thread *td)
void
save_vec(struct thread *td)
{
- int msr;
- struct pcb *pcb;
+ struct pcb *pcb;
pcb = td->td_pcb;
- /*
- * Temporarily re-enable the vector unit during the save
- */
- msr = mfmsr();
- mtmsr(msr | PSL_VEC);
- isync();
-
- /*
- * Save the vector registers and VSCR to the PCB
- */
-#define STVX(n) __asm ("stvx %1,0,%0" \
- :: "b"(pcb->pcb_vec.vr[n]), "n"(n));
- STVX(0); STVX(1); STVX(2); STVX(3);
- STVX(4); STVX(5); STVX(6); STVX(7);
- STVX(8); STVX(9); STVX(10); STVX(11);
- STVX(12); STVX(13); STVX(14); STVX(15);
- STVX(16); STVX(17); STVX(18); STVX(19);
- STVX(20); STVX(21); STVX(22); STVX(23);
- STVX(24); STVX(25); STVX(26); STVX(27);
- STVX(28); STVX(29); STVX(30); STVX(31);
-#undef STVX
-
- __asm __volatile("mfvscr 0; stvewx 0,0,%0" :: "b"(&pcb->pcb_vec.vscr));
-
- /*
- * Disable vector unit again
- */
- isync();
- mtmsr(msr);
+ save_vec_int(td);
/*
* Clear the current vec thread and pcb's CPU id
@@ -150,3 +161,19 @@ save_vec(struct thread *td)
PCPU_SET(vecthread, NULL);
}
+/*
+ * Save altivec state without dropping ownership. This will only save state if
+ * the current vector-thread is `td'.
+ */
+void
+save_vec_nodrop(struct thread *td)
+{
+ struct thread *vtd;
+
+ vtd = PCPU_GET(vecthread);
+ if (td != vtd) {
+ return;
+ }
+
+ save_vec_int(td);
+}
diff --git a/sys/powerpc/powerpc/elf32_machdep.c b/sys/powerpc/powerpc/elf32_machdep.c
index 2c62df2..1e0b43b 100644
--- a/sys/powerpc/powerpc/elf32_machdep.c
+++ b/sys/powerpc/powerpc/elf32_machdep.c
@@ -47,6 +47,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
+#include <machine/altivec.h>
#include <machine/cpu.h>
#include <machine/elf.h>
#include <machine/reg.h>
@@ -147,9 +148,24 @@ SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
&freebsd_brand_oinfo);
void
-elf32_dump_thread(struct thread *td __unused, void *dst __unused,
- size_t *off __unused)
+elf32_dump_thread(struct thread *td, void *dst, size_t *off)
{
+ size_t len;
+ struct pcb *pcb;
+
+ 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,
+ sizeof(pcb->pcb_vec), NULL);
+ } else
+ len += elf32_populate_note(NT_PPC_VMX, NULL, NULL,
+ sizeof(pcb->pcb_vec), NULL);
+ }
+ *off = len;
}
#ifndef __powerpc64__
diff --git a/sys/powerpc/powerpc/elf64_machdep.c b/sys/powerpc/powerpc/elf64_machdep.c
index 0c41a8d..a0fc7b7 100644
--- a/sys/powerpc/powerpc/elf64_machdep.c
+++ b/sys/powerpc/powerpc/elf64_machdep.c
@@ -44,6 +44,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
+#include <machine/altivec.h>
#include <machine/cpu.h>
#include <machine/elf.h>
#include <machine/md_var.h>
@@ -119,9 +120,24 @@ SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
&freebsd_brand_oinfo);
void
-elf64_dump_thread(struct thread *td __unused, void *dst __unused,
- size_t *off __unused)
+elf64_dump_thread(struct thread *td, void *dst, size_t *off)
{
+ size_t len;
+ struct pcb *pcb;
+
+ 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,
+ sizeof(pcb->pcb_vec), NULL);
+ } else
+ len += elf64_populate_note(NT_PPC_VMX, NULL, NULL,
+ sizeof(pcb->pcb_vec), NULL);
+ }
+ *off = len;
}
OpenPOWER on IntegriCloud