Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/vfp Improve PCU/VFP handling to the point that ...



details:   https://anonhg.NetBSD.org/src/rev/3025f4d8d45e
branches:  trunk
changeset: 326321:3025f4d8d45e
user:      skrll <skrll%NetBSD.org@localhost>
date:      Sat Jan 25 17:30:56 2014 +0000

description:
Improve PCU/VFP handling to the point that the atf tests don't trigger
KASSERTs on the Raspberry PI and its arm1176jzf-s.

XXX Need to emulate bounce instructions to get correct exception codes,
XXX etc.

diffstat:

 sys/arch/arm/vfp/vfp_init.c |  65 ++++++++++++++++++++++++++------------------
 1 files changed, 38 insertions(+), 27 deletions(-)

diffs (129 lines):

diff -r e32c44dfacfe -r 3025f4d8d45e sys/arch/arm/vfp/vfp_init.c
--- a/sys/arch/arm/vfp/vfp_init.c       Sat Jan 25 17:30:45 2014 +0000
+++ b/sys/arch/arm/vfp/vfp_init.c       Sat Jan 25 17:30:56 2014 +0000
@@ -1,4 +1,4 @@
-/*      $NetBSD: vfp_init.c,v 1.32 2014/01/24 08:26:39 skrll Exp $ */
+/*      $NetBSD: vfp_init.c,v 1.33 2014/01/25 17:30:56 skrll Exp $ */
 
 /*
  * Copyright (c) 2008 ARM Ltd
@@ -407,14 +407,18 @@
 
                vfpevent_fpe.ev_count++;
 
+               /*
+                * Need the clear the exception condition so any signal
+                * and future use can proceed.
+                */
+               armreg_fpexc_write(fpexc & ~(VFP_FPEXC_EX|VFP_FPEXC_FSUM));
+
                pcu_save(&arm_vfp_ops);
 
                /*
-                * Need the clear the exception condition so any signal
-                * can run.
+                * XXX Need to emulate bounce instructions here to get correct
+                * XXX exception codes, etc.
                 */
-               armreg_fpexc_write(fpexc & ~(VFP_FPEXC_EX|VFP_FPEXC_FSUM));
-
                KSI_INIT_TRAP(&ksi);
                ksi.ksi_signo = SIGFPE;
                if (fpexc & VFP_FPEXC_IXF)
@@ -499,6 +503,7 @@
         * a trap to use it again" event.
         */
        if (__predict_false((flags & PCU_LOADED) == 0)) {
+               KASSERT(flags & PCU_RELOAD);
                vfpevent_use.ev_count++;
                pcb->pcb_vfp.vfp_fpscr =
                    (VFP_FPSCR_DN | VFP_FPSCR_FZ | VFP_FPSCR_RN); /* Runfast */
@@ -506,21 +511,24 @@
                vfpevent_reuse.ev_count++;
        }
 
-       if (fregs->vfp_fpexc & VFP_FPEXC_EN) {
+       uint32_t fpexc = armreg_fpexc_read();
+       if (flags & PCU_RELOAD) {
+               bool enabled = fregs->vfp_fpexc & VFP_FPEXC_EN;
+
                /*
-                * If we think the VFP is enabled, it must have be disabled by
-                * vfp_state_release for another LWP so we can just restore
-                * FPEXC and return since our VFP state is still loaded.
+                * Load and Enable the VFP (so that we can write the
+                * registers).
                 */
+               fregs->vfp_fpexc |= VFP_FPEXC_EN;
                armreg_fpexc_write(fregs->vfp_fpexc);
-               return;
-       }
-
-       /* Load and Enable the VFP (so that we can write the registers).  */
-       if (flags & PCU_RELOAD) {
-               uint32_t fpexc = armreg_fpexc_read();
-               KDASSERT((fpexc & VFP_FPEXC_EX) == 0);
-               armreg_fpexc_write(fpexc | VFP_FPEXC_EN);
+               if (enabled) {
+                       /*
+                        * If we think the VFP is enabled, it must have be
+                        * disabled by vfp_state_release for another LWP so
+                        * we can now just return.
+                        */
+                       return;
+               }
 
                load_vfpregs(fregs);
                armreg_fpscr_write(fregs->vfp_fpscr);
@@ -531,11 +539,13 @@
                        if (fregs->vfp_fpexc & VFP_FPEXC_FP2V)
                                armreg_fpinst_write(fregs->vfp_fpinst);
                }
+       } else {
+               /*
+                * If the VFP is already enabled we must be bouncing an
+                * instruction.
+                */
+               armreg_fpexc_write(fpexc | VFP_FPEXC_EN);
        }
-
-       /* Finally, restore the FPEXC but don't enable the VFP. */
-       fregs->vfp_fpexc |= VFP_FPEXC_EN;
-       armreg_fpexc_write(fregs->vfp_fpexc);
 }
 
 void
@@ -543,6 +553,12 @@
 {
        struct pcb * const pcb = lwp_getpcb(l);
        uint32_t fpexc = armreg_fpexc_read();
+
+       /*
+        * Enable the VFP (so we can read the registers).
+        * Make sure the exception bit is cleared so that we can
+        * safely dump the registers.
+        */
        armreg_fpexc_write((fpexc | VFP_FPEXC_EN) & ~VFP_FPEXC_EX);
 
        if (flags & PCU_KERNEL) {
@@ -556,11 +572,6 @@
 
        struct vfpreg * const fregs = &pcb->pcb_vfp;
 
-       /*
-        * Enable the VFP (so we can read the registers).  
-        * Make sure the exception bit is cleared so that we can
-        * safely dump the registers.
-        */
        fregs->vfp_fpexc = fpexc;
        if (fpexc & VFP_FPEXC_EX) {
                /* Need to save the exception handling state */
@@ -572,7 +583,7 @@
        save_vfpregs(fregs);
 
        /* Disable the VFP.  */
-       armreg_fpexc_write(fpexc);
+       armreg_fpexc_write(fpexc & ~VFP_FPEXC_EN);
 }
 
 void



Home | Main Index | Thread Index | Old Index