runtime: fix fault during arm software floating point

The software floating point runs with m->locks++
to avoid being preempted; recognize this case in panic
and undo it so that m->locks is maintained correctly
when panicking.

Fixes #7553.

LGTM=dvyukov
R=golang-codereviews, dvyukov
CC=golang-codereviews
https://golang.org/cl/84030043
diff --git a/src/pkg/runtime/panic.c b/src/pkg/runtime/panic.c
index 0bf3b6a..3af8cb6 100644
--- a/src/pkg/runtime/panic.c
+++ b/src/pkg/runtime/panic.c
@@ -498,7 +498,7 @@
 	// and not stuck in a system call.
 	if(gp == nil || gp != m->curg)
 		return false;
-	if(m->locks != 0 || m->mallocing != 0 || m->throwing != 0 || m->gcing != 0 || m->dying != 0)
+	if(m->locks-m->softfloat != 0 || m->mallocing != 0 || m->throwing != 0 || m->gcing != 0 || m->dying != 0)
 		return false;
 	if(gp->status != Grunning || gp->syscallsp != 0)
 		return false;
@@ -526,6 +526,16 @@
 {
 	Eface err;
 
+	// m->softfloat is set during software floating point,
+	// which might cause a fault during a memory load.
+	// It increments m->locks to avoid preemption.
+	// If we're panicking, the software floating point frames
+	// will be unwound, so decrement m->locks as they would.
+	if(m->softfloat) {
+		m->locks--;
+		m->softfloat = 0;
+	}
+
 	if(m->mallocing) {
 		runtime·printf("panic: %s\n", s);
 		runtime·throw("panic during malloc");
@@ -534,6 +544,10 @@
 		runtime·printf("panic: %s\n", s);
 		runtime·throw("panic during gc");
 	}
+	if(m->locks) {
+		runtime·printf("panic: %s\n", s);
+		runtime·throw("panic holding locks");
+	}
 	runtime·newErrorCString(s, &err);
 	runtime·panic(err);
 }
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 28c831a0..0ba1238 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -312,6 +312,7 @@
 	int32	throwing;
 	int32	gcing;
 	int32	locks;
+	int32	softfloat;
 	int32	dying;
 	int32	profilehz;
 	int32	helpgc;
diff --git a/src/pkg/runtime/vlop_arm.s b/src/pkg/runtime/vlop_arm.s
index 941de3e..80f516e 100644
--- a/src/pkg/runtime/vlop_arm.s
+++ b/src/pkg/runtime/vlop_arm.s
@@ -75,10 +75,14 @@
 	MOVW	m_locks(m), R1
 	ADD	$1, R1
 	MOVW	R1, m_locks(m)
+	MOVW	$1, R1
+	MOVW	R1, m_softfloat(m)
 	BL	runtime·_sfloat2(SB)
 	MOVW	m_locks(m), R1
 	SUB	$1, R1
 	MOVW	R1, m_locks(m)
+	MOVW	$0, R1
+	MOVW	R1, m_softfloat(m)
 	MOVW	R0, 0(R13)
 	MOVW	64(R13), R1
 	WORD	$0xe128f001	// msr cpsr_f, r1