NetBSD-Bugs archive

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

Re: port-arm/52603: arm(v7?) vfp register corruption



More KASSERT(), this time in mi_switch():

Index: kern/kern_synch.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_synch.c,v
retrieving revision 1.311
diff -u -p -u -r1.311 kern_synch.c
--- kern/kern_synch.c	3 Jul 2016 14:24:58 -0000	1.311
+++ kern/kern_synch.c	15 Oct 2017 18:54:34 -0000
@@ -97,6 +97,9 @@ __KERNEL_RCSID(0, "$NetBSD: kern_synch.c
 #include <sys/atomic.h>
 #include <sys/syslog.h>
 
+#include <arm/pcb.h>
+#include <arm/vfpreg.h>
+
 #include <uvm/uvm_extern.h>
 
 #include <dev/lockstat.h>
@@ -503,6 +506,7 @@ nextlwp(struct cpu_info *ci, struct sche
  *
  * Returns 1 if another LWP was actually run.
  */
+__asm(".fpu\tvfpv4");
 int
 mi_switch(lwp_t *l)
 {
@@ -724,13 +728,44 @@ mi_switch(lwp_t *l)
 		KASSERTMSG(l == curlwp, "l %p curlwp %p prevlwp %p",
 		    l, curlwp, prevlwp);
 
+		KASSERTMSG(l->l_switchto == NULL, "l %p curlwp %p prevlwp %p l->l_switchto %p", l, curlwp, prevlwp, l->l_switchto);
+		if ((l->l_flag & LW_SYSTEM) == 0) {
+			KASSERTMSG(((struct pcb *)lwp_getpcb(l))->pcb_vfp.vfp_fpexc == armreg_fpexc_read(),
+			    "fpexc 0x%x prev 0x%x reg 0x%x l %p/%p", 
+			    ((struct pcb *)lwp_getpcb(l))->pcb_vfp.vfp_fpexc,
+			    ((struct pcb *)lwp_getpcb(prevlwp))->pcb_vfp.vfp_fpexc,
+			    armreg_fpexc_read(),
+			    l, prevlwp);
+		} else {
+			KASSERT((l->l_pcu_valid & (1 << PCU_FPU)) == 0);
+		}
+
 		/*
 		 * Switched away - we have new curlwp.
 		 * Restore VM context and IPL.
 		 */
 		pmap_activate(l);
 		uvm_emap_switch(l);
+		if ((l->l_flag & LW_SYSTEM) == 0) {
+			KASSERTMSG(((struct pcb *)lwp_getpcb(l))->pcb_vfp.vfp_fpexc == armreg_fpexc_read(),
+			    "XXX fpexc 0x%x prev 0x%x reg 0x%x l %p/%p", 
+			    ((struct pcb *)lwp_getpcb(l))->pcb_vfp.vfp_fpexc,
+			    ((struct pcb *)lwp_getpcb(prevlwp))->pcb_vfp.vfp_fpexc,
+			    armreg_fpexc_read(),
+			    l, prevlwp);
+		} else {
+			KASSERT((l->l_pcu_valid & (1 << PCU_FPU)) == 0);
+		}
 		pcu_switchpoint(l);
+		if ((l->l_flag & LW_SYSTEM) == 0) {
+			KASSERTMSG(((struct pcb *)lwp_getpcb(l))->pcb_vfp.vfp_fpexc == armreg_fpexc_read(),
+			    "fpexc 0x%x/0x%x l %p/%p", 
+			    ((struct pcb *)lwp_getpcb(l))->pcb_vfp.vfp_fpexc,
+			    armreg_fpexc_read(),
+			    l, prevlwp);
+		} else {
+			KASSERT((l->l_pcu_valid & (1 << PCU_FPU)) == 0);
+		}
 
 		if (prevlwp != NULL) {
 			/* Normalize the count of the spin-mutexes */


note that the KASSERTMSG() before and after pmap_activate() are the same.
The KASSERTMSG() after pmap_activate() fired twice, this means that
actually cpu_switchto() works as expected, and the FPU is reenabled
after, probably by an interrupt.

Another KASSERT proved me that IPIs are allowed in this portion of code,
but I can't see where we could fail to disable the fpu before exiting the
handler ...

-- 
Manuel Bouyer <bouyer%antioche.eu.org@localhost>
     NetBSD: 26 ans d'experience feront toujours la difference
--


Home | Main Index | Thread Index | Old Index