Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch restructure the FPU and AltiVEC code so that it wor...



details:   https://anonhg.NetBSD.org/src/rev/e6237ef21663
branches:  trunk
changeset: 534495:e6237ef21663
user:      chs <chs%NetBSD.org@localhost>
date:      Sun Jul 28 07:07:44 2002 +0000

description:
restructure the FPU and AltiVEC code so that it works for MP.

diffstat:

 sys/arch/macppc/include/intr.h             |   11 +-
 sys/arch/macppc/macppc/machdep.c           |   90 ++++++++++++++-----
 sys/arch/powerpc/include/altivec.h         |   10 +-
 sys/arch/powerpc/include/fpu.h             |    9 +-
 sys/arch/powerpc/mpc6xx/altivec.c          |  133 +++++++++++++++++++++-------
 sys/arch/powerpc/powerpc/fpu.c             |  103 ++++++++++++++++++---
 sys/arch/powerpc/powerpc/process_machdep.c |    8 +-
 sys/arch/powerpc/powerpc/trap.c            |   67 +++++---------
 sys/arch/powerpc/powerpc/vm_machdep.c      |   19 +--
 9 files changed, 307 insertions(+), 143 deletions(-)

diffs (truncated from 811 to 300 lines):

diff -r 3aa08507a652 -r e6237ef21663 sys/arch/macppc/include/intr.h
--- a/sys/arch/macppc/include/intr.h    Sun Jul 28 07:07:00 2002 +0000
+++ b/sys/arch/macppc/include/intr.h    Sun Jul 28 07:07:44 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: intr.h,v 1.14 2002/07/05 18:45:17 matt Exp $   */
+/*     $NetBSD: intr.h,v 1.15 2002/07/28 07:07:46 chs Exp $    */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -139,12 +139,13 @@
 #define CNT_SOFTNET    66
 #define CNT_SOFTSERIAL 67
 
-#define MACPPC_IPI_HALT                0x01
-#define MACPPC_IPI_FLUSH_FPU   0x02
+#ifdef MULTIPROCESSOR
+#define MACPPC_IPI_HALT                0x0001
+#define MACPPC_IPI_FLUSH_FPU   0x0002
+#define MACPPC_IPI_FLUSH_VEC   0x0004
 
-#ifdef MULTIPROCESSOR
 struct cpu_info;
-void macppc_send_ipi(volatile struct cpu_info *, int);
+void macppc_send_ipi(volatile struct cpu_info *, u_long);
 #endif
 
 #endif /* _LOCORE */
diff -r 3aa08507a652 -r e6237ef21663 sys/arch/macppc/macppc/machdep.c
--- a/sys/arch/macppc/macppc/machdep.c  Sun Jul 28 07:07:00 2002 +0000
+++ b/sys/arch/macppc/macppc/machdep.c  Sun Jul 28 07:07:44 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.116 2002/07/09 19:21:03 matt Exp $       */
+/*     $NetBSD: machdep.c,v 1.117 2002/07/28 07:07:46 chs Exp $        */
 
 /*
  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -35,6 +35,7 @@
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
 #include "opt_ipkdb.h"
+#include "opt_altivec.h"
 #include "opt_multiprocessor.h"
 #include "adb.h"
 #include "zsc.h"
@@ -79,6 +80,9 @@
 #include <machine/trap.h>
 #include <machine/bus.h>
 #include <machine/fpu.h>
+#ifdef ALTIVEC
+#include <powerpc/altivec.h>
+#endif
 
 #include <dev/cons.h>
 #include <dev/ofw/openfirm.h>
@@ -673,43 +677,81 @@
 }
 
 #ifdef MULTIPROCESSOR
+/*
+ * Save a process's FPU state to its PCB.  The state is in another CPU
+ * (though by the time our IPI is processed, it may have been flushed already).
+ */
 void
-save_fpu_proc(p)
+mp_save_fpu_proc(p)
        struct proc *p;
 {
-       volatile struct cpu_info *fpcpu;
+       struct pcb *pcb = &p->p_addr->u_pcb;
+       struct cpu_info *fpcpu;
        int i;
-       extern volatile int IPI[];      /* XXX */
 
-       fpcpu = p->p_addr->u_pcb.pcb_fpcpu;
-       if (fpcpu == curcpu()) {
-               save_fpu(p);
-               return;
-       }
+       /*
+        * Send an IPI to the other CPU with the data and wait for that CPU
+        * to flush the data.  Note that the other CPU might have switched
+        * to a different proc's FPU state by the time it receives the IPI,
+        * but that will only result in an unnecessary reload.
+        */
 
-#if 0
-       printf("save_fpu_proc{%d} pid = %d, fpcpu->ci_cpuid = %d\n",
-           cpu_number(), p->p_pid, fpcpu->ci_cpuid);
-#endif
-
+       fpcpu = pcb->pcb_fpcpu;
        macppc_send_ipi(fpcpu, MACPPC_IPI_FLUSH_FPU);
 
        /* Wait for flush. */
 #if 0
-       while (fpcpu->ci_fpuproc);
+       while (pcb->pcb_fpcpu)
+               ;
 #else
        for (i = 0; i < 0x3fffffff; i++) {
-               if (fpcpu->ci_fpuproc == NULL)
-                       goto done;
+               if (pcb->pcb_fpcpu == NULL)
+                       return;
        }
-       printf("save_fpu_proc{%d} pid = %d, fpcpu->ci_cpuid = %d\n",
+       printf("mp_save_fpu_proc{%d} pid = %d, fpcpu->ci_cpuid = %d\n",
            cpu_number(), p->p_pid, fpcpu->ci_cpuid);
-       printf("IPI[0] = 0x%x, IPI[1] = 0x%x\n", IPI[0], IPI[1]);
-       printf("cpl 0x%x 0x%x\n", cpu_info[0].ci_cpl, cpu_info[1].ci_cpl);
-       printf("ipending 0x%x 0x%x\n", cpu_info[0].ci_ipending, cpu_info[1].ci_ipending);
-       panic("save_fpu_proc");
-done:;
-
+       panic("mp_save_fpu_proc");
 #endif
 }
+
+#ifdef ALTIVEC
+/*
+ * Save a process's AltiVEC state to its PCB.  The state may be in any CPU.
+ * The process must either be curproc or traced by curproc (and stopped).
+ * (The point being that the process must not run on another CPU during
+ * this function).
+ */
+void
+mp_save_vec_proc(p)
+       struct proc *p;
+{
+       struct pcb *pcb = &p->p_addr->u_pcb;
+       struct cpu_info *veccpu;
+       int i;
+
+       /*
+        * Send an IPI to the other CPU with the data and wait for that CPU
+        * to flush the data.  Note that the other CPU might have switched
+        * to a different proc's AltiVEC state by the time it receives the IPI,
+        * but that will only result in an unnecessary reload.
+        */
+
+       veccpu = pcb->pcb_veccpu;
+       macppc_send_ipi(veccpu, MACPPC_IPI_FLUSH_VEC);
+
+       /* Wait for flush. */
+#if 0
+       while (pcb->pcb_veccpu)
+               ;
+#else
+       for (i = 0; i < 0x3fffffff; i++) {
+               if (pcb->pcb_veccpu == NULL)
+                       return;
+       }
+       printf("mp_save_vec_proc{%d} pid = %d, veccpu->ci_cpuid = %d\n",
+           cpu_number(), p->p_pid, veccpu->ci_cpuid);
+       panic("mp_save_vec_proc");
+#endif
+}
+#endif /* ALTIVEC */
 #endif /* MULTIPROCESSOR */
diff -r 3aa08507a652 -r e6237ef21663 sys/arch/powerpc/include/altivec.h
--- a/sys/arch/powerpc/include/altivec.h        Sun Jul 28 07:07:00 2002 +0000
+++ b/sys/arch/powerpc/include/altivec.h        Sun Jul 28 07:07:44 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: altivec.h,v 1.3 2002/07/18 22:51:57 matt Exp $ */
+/*     $NetBSD: altivec.h,v 1.4 2002/07/28 07:07:44 chs Exp $  */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -43,8 +43,12 @@
 #define        VSCR_NJ         0x00010000      /* Non Java-IEEE-C9X FP mode */
 
 #ifdef _KERNEL
-void save_vec(struct proc *p);
-void enable_vec(struct proc *p);
+void enable_vec(void);
+void save_vec_cpu(void);
+void save_vec_proc(struct proc *);
+#ifdef MULTIPROCESSOR
+void mp_save_vec_proc(struct proc *);
+#endif
 void init_vec(void);
 void vzeropage(paddr_t);
 void vcopypage(paddr_t, paddr_t);      /* dst, src */
diff -r 3aa08507a652 -r e6237ef21663 sys/arch/powerpc/include/fpu.h
--- a/sys/arch/powerpc/include/fpu.h    Sun Jul 28 07:07:00 2002 +0000
+++ b/sys/arch/powerpc/include/fpu.h    Sun Jul 28 07:07:44 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: fpu.h,v 1.6 2002/05/19 16:55:43 jdolecek Exp $ */
+/*     $NetBSD: fpu.h,v 1.7 2002/07/28 07:07:44 chs Exp $      */
 
 /*-
  * Copyright (C) 1996 Wolfgang Solfrank.
@@ -76,9 +76,12 @@
 #if defined(PPC_MPC6XX)
 #define PPC_HAVE_FPU
 
-void   enable_fpu(struct proc *);
-void   save_fpu(struct proc *);
+void   enable_fpu(void);
+void   save_fpu_cpu(void);
 void   save_fpu_proc(struct proc *);
+#ifdef MULTIPROCESSOR
+void   mp_save_fpu_proc(struct proc *);
+#endif
 #endif /* PPC_HAVE_FPU */
 #endif /* _KERNEL */
 
diff -r 3aa08507a652 -r e6237ef21663 sys/arch/powerpc/mpc6xx/altivec.c
--- a/sys/arch/powerpc/mpc6xx/altivec.c Sun Jul 28 07:07:00 2002 +0000
+++ b/sys/arch/powerpc/mpc6xx/altivec.c Sun Jul 28 07:07:44 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: altivec.c,v 1.5 2002/07/25 23:46:47 matt Exp $ */
+/*     $NetBSD: altivec.c,v 1.6 2002/07/28 07:07:45 chs Exp $  */
 
 /*
  * Copyright (C) 1996 Wolfgang Solfrank.
@@ -44,17 +44,16 @@
 struct pool vecpool;
 
 void
-enable_vec(struct proc *p)
+enable_vec()
 {
+       struct cpu_info *ci = curcpu();
+       struct proc *p = curproc;
        struct pcb *pcb = &p->p_addr->u_pcb;
        struct trapframe *tf = trapframe(p);
        struct vreg *vr = pcb->pcb_vr;
        int msr, scratch;
 
-       /*
-        * Enable AltiVec when we return to user-mode.
-        */
-       tf->srr1 |= PSL_VEC;
+       KASSERT(pcb->pcb_veccpu == NULL);
 
        /*
         * Allocate a vreg structure if we haven't done so.
@@ -62,9 +61,11 @@
        if (!(pcb->pcb_flags & PCB_ALTIVEC)) {
                vr = pcb->pcb_vr = pool_get(&vecpool, PR_WAITOK);
                pcb->pcb_flags |= PCB_ALTIVEC;
+
                /*
                 * Initialize the vectors with NaNs
                 */
+
                for (scratch = 0; scratch < 32; scratch++) {
                        vr->vreg[scratch][0] = 0x7FFFDEAD;
                        vr->vreg[scratch][1] = 0x7FFFDEAD;
@@ -76,16 +77,20 @@
        }
 
        /*
-        * Enable AltiVec temporarily
+        * Enable AltiVec temporarily (and disable interrupts).
         */
-       __asm __volatile ("mfmsr %0; oris %1,%0,%2@h; mtmsr %1; isync"
-           :   "=r"(msr), "=r"(scratch)
-           :   "J"(PSL_VEC));
+       msr = mfmsr();
+       mtmsr((msr & ~PSL_EE) | PSL_VEC);
+       __asm __volatile ("isync");
+       if (ci->ci_vecproc) {
+               save_vec_cpu();
+       }
+       KASSERT(curcpu()->ci_vecproc == NULL);
 
        /*
         * Restore VSCR by first loading it into a vector and then into VSCR.
         * (this needs to done before loading the user's vector registers
-        * since we need to a scratch vector register)
+        * since we need to use a scratch vector register)
         */
        __asm __volatile("vxor %2,%2,%2; lvewx %2,%0,%1; mtvscr %2" \
            ::  "r"(vr), "r"(offsetof(struct vreg, vscr)), "n"(0));
@@ -110,27 +115,46 @@
        LVX(20,vr);     LVX(21,vr);     LVX(22,vr);     LVX(23,vr);
        LVX(24,vr);     LVX(25,vr);     LVX(26,vr);     LVX(27,vr);
        LVX(28,vr);     LVX(29,vr);     LVX(30,vr);     LVX(31,vr);
+       __asm __volatile ("isync");
+
+       /*
+        * Enable AltiVec when we return to user-mode.
+        * Record the new ownership of the AltiVec unit.
+        */
+       tf->srr1 |= PSL_VEC;
+       curcpu()->ci_vecproc = p;
+       pcb->pcb_veccpu = curcpu();
+       __asm __volatile ("sync");
 
        /*
         * Restore MSR (turn off AltiVec)
         */
-       __asm __volatile ("mtmsr %0; isync" :: "r"(msr));
+       mtmsr(msr);
 }
 
 void
-save_vec(struct proc *p)



Home | Main Index | Thread Index | Old Index