summaryrefslogtreecommitdiff
path: root/sys/arch/hppa
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2010-07-02 00:00:46 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2010-07-02 00:00:46 +0000
commit4116d8a387370fa5be708ad38892a9e7ca9d7bb8 (patch)
treee45914ea1723ae3f1edcb36289eedc74e830cc8b /sys/arch/hppa
parent9d16e6d6f8faf9ee3792c194615a0c6b883eae82 (diff)
Implement FPU shootdowns for hppa multiprocessor kernels. There are still
some subtle bugs however these can be fixed in tree. ok kettenis@
Diffstat (limited to 'sys/arch/hppa')
-rw-r--r--sys/arch/hppa/hppa/fpu.c88
-rw-r--r--sys/arch/hppa/hppa/ipi.c22
-rw-r--r--sys/arch/hppa/include/fpu.h3
-rw-r--r--sys/arch/hppa/include/intr.h12
4 files changed, 110 insertions, 15 deletions
diff --git a/sys/arch/hppa/hppa/fpu.c b/sys/arch/hppa/hppa/fpu.c
index 2661ea92551..6e13acc51ee 100644
--- a/sys/arch/hppa/hppa/fpu.c
+++ b/sys/arch/hppa/hppa/fpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fpu.c,v 1.1 2010/06/29 04:03:21 jsing Exp $ */
+/* $OpenBSD: fpu.c,v 1.2 2010/07/02 00:00:45 jsing Exp $ */
/*
* Copyright (c) 2010 Joel Sing <jsing@openbsd.org>
@@ -19,35 +19,103 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
+#include <sys/user.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/fpu.h>
+#include <machine/intr.h>
#include <machine/pcb.h>
#include <machine/reg.h>
+__inline void fpu_proc(struct proc *, int);
+
void
fpu_proc_flush(struct proc *p)
{
+ fpu_proc(p, 0);
+}
+
+void
+fpu_proc_save(struct proc *p)
+{
+ fpu_proc(p, 1);
+}
+
+__inline void
+fpu_proc(struct proc *p, int save)
+{
struct cpu_info *ci = curcpu();
+ struct hppa_fpstate *hfp;
+ struct cpu_info *fpuci;
+#ifdef MULTIPROCESSOR
+ int s;
+#endif
+
+ hfp = (struct hppa_fpstate *)p->p_md.md_regs->tf_cr30;
+ fpuci = (struct cpu_info *)hfp->hfp_cpu;
+
+ if (fpuci == NULL)
+ return;
+
+#ifdef MULTIPROCESSOR
+ if (fpuci != ci) {
+
+ if (hppa_ipi_send(fpuci, HPPA_IPI_FPU_SAVE))
+ panic("FPU shootdown failed!\n");
+
+ while (hfp->hfp_cpu != NULL)
+ ;
+
+ } else if (p->p_md.md_regs->tf_cr30 == ci->ci_fpu_state) {
+
+ s = splipi();
+ fpu_cpu_save(save);
+ splx(s);
- /* Flush process FPU state from CPU. */
- if (p->p_md.md_regs->tf_cr30 == ci->ci_fpu_state) {
- fpu_exit();
- ci->ci_fpu_state = 0;
}
+#else
+ if (p->p_md.md_regs->tf_cr30 == ci->ci_fpu_state)
+ fpu_cpu_save(save);
+#endif
}
+/*
+ * Save or flush FPU state - note that this must be called at IPL IPI when
+ * running on a MULTIPROCESSOR kernel.
+ */
void
-fpu_proc_save(struct proc *p)
+fpu_cpu_save(int save)
{
struct cpu_info *ci = curcpu();
+ struct hppa_fpstate *hfp;
+ struct cpu_info *fpuci;
extern u_int fpu_enable;
- /* Save process FPU state. */
- if (p->p_md.md_regs->tf_cr30 == ci->ci_fpu_state) {
+#ifdef MULTIPROCESSOR
+ splassert(IPL_IPI);
+#endif
+
+ if (ci->ci_fpu_state == 0)
+ return;
+
+ hfp = (struct hppa_fpstate *)ci->ci_fpu_state;
+ fpuci = (struct cpu_info *)hfp->hfp_cpu;
+
+#ifdef DIAGNOSTIC
+ if (fpuci != ci)
+ panic("FPU context is not on this CPU (%p != %p)\n",
+ ci, hfp->hfp_cpu);
+#endif
+
+ if (save) {
mtctl(fpu_enable, CR_CCR);
- fpu_save(ci->ci_fpu_state);
+ fpu_save((paddr_t)&hfp->hfp_regs);
mtctl(0, CR_CCR);
- }
+ } else
+ fpu_exit();
+
+ hfp->hfp_cpu = NULL;
+ ci->ci_fpu_state = 0;
+ asm volatile ("sync" ::: "memory");
}
diff --git a/sys/arch/hppa/hppa/ipi.c b/sys/arch/hppa/hppa/ipi.c
index f3f0aec7500..e4bac94a456 100644
--- a/sys/arch/hppa/hppa/ipi.c
+++ b/sys/arch/hppa/hppa/ipi.c
@@ -1,3 +1,5 @@
+/* $OpenBSD: ipi.c,v 1.2 2010/07/02 00:00:45 jsing Exp $ */
+
/*
* Copyright (c) 2010 Joel Sing <jsing@openbsd.org>
*
@@ -14,22 +16,28 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/mutex.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
+#include <machine/fpu.h>
#include <machine/iomod.h>
#include <machine/intr.h>
#include <machine/mutex.h>
#include <machine/reg.h>
void hppa_ipi_nop(void);
+void hppa_ipi_fpu_save(void);
+void hppa_ipi_fpu_flush(void);
void (*ipifunc[HPPA_NIPI])(void) =
{
- hppa_ipi_nop
+ hppa_ipi_nop,
+ hppa_ipi_fpu_save,
+ hppa_ipi_fpu_flush
};
void
@@ -88,3 +96,15 @@ void
hppa_ipi_nop(void)
{
}
+
+void
+hppa_ipi_fpu_save(void)
+{
+ fpu_cpu_save(1);
+}
+
+void
+hppa_ipi_fpu_flush(void)
+{
+ fpu_cpu_save(0);
+}
diff --git a/sys/arch/hppa/include/fpu.h b/sys/arch/hppa/include/fpu.h
index 162a6b62917..18acaf53d1d 100644
--- a/sys/arch/hppa/include/fpu.h
+++ b/sys/arch/hppa/include/fpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: fpu.h,v 1.2 2010/07/01 05:33:32 jsing Exp $ */
+/* $OpenBSD: fpu.h,v 1.3 2010/07/02 00:00:45 jsing Exp $ */
/*
* Copyright (c) 2010 Joel Sing <jsing@openbsd.org>
@@ -29,5 +29,6 @@ struct hppa_fpstate {
void fpu_proc_flush(struct proc *);
void fpu_proc_save(struct proc *);
+void fpu_cpu_save(int);
#endif /* _MACHINE_FPU_H_ */
diff --git a/sys/arch/hppa/include/intr.h b/sys/arch/hppa/include/intr.h
index bb53e635bc8..692044d6d98 100644
--- a/sys/arch/hppa/include/intr.h
+++ b/sys/arch/hppa/include/intr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.h,v 1.33 2010/07/01 03:38:50 jsing Exp $ */
+/* $OpenBSD: intr.h,v 1.34 2010/07/02 00:00:45 jsing Exp $ */
/*
* Copyright (c) 2002-2004 Michael Shalayeff
@@ -57,8 +57,9 @@
#ifdef MULTIPROCESSOR
#define HPPA_IPI_NOP 0
-
-#define HPPA_NIPI 1
+#define HPPA_IPI_FPU_SAVE 1
+#define HPPA_IPI_FPU_FLUSH 2
+#define HPPA_NIPI 3
#endif
#if !defined(_LOCORE) && defined(_KERNEL)
@@ -149,6 +150,11 @@ hppa_intr_enable(register_t eiem)
#define SOFTINT_MASK ((1 << (IPL_SOFTCLOCK - 1)) | \
(1 << (IPL_SOFTNET - 1)) | (1 << (IPL_SOFTTTY - 1)))
+#ifdef MULTIPROCESSOR
+void hppa_ipi_init(struct cpu_info *);
+int hppa_ipi_send(struct cpu_info *, u_long);
+#endif
+
#define setsoftast(p) (p->p_md.md_astpending = 1)
#define setsoftnet() softintr(1 << (IPL_SOFTNET - 1))