diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2010-07-02 00:00:46 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2010-07-02 00:00:46 +0000 |
commit | 4116d8a387370fa5be708ad38892a9e7ca9d7bb8 (patch) | |
tree | e45914ea1723ae3f1edcb36289eedc74e830cc8b /sys/arch/hppa | |
parent | 9d16e6d6f8faf9ee3792c194615a0c6b883eae82 (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.c | 88 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/ipi.c | 22 | ||||
-rw-r--r-- | sys/arch/hppa/include/fpu.h | 3 | ||||
-rw-r--r-- | sys/arch/hppa/include/intr.h | 12 |
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)) |