git: 570206bdc227 - stable/13 - arm64: Enable the floating-point exception traps

From: Dmitry Chagin <dchagin_at_FreeBSD.org>
Date: Fri, 17 Jun 2022 19:40:48 UTC
The branch stable/13 has been updated by dchagin:

URL: https://cgit.FreeBSD.org/src/commit/?id=570206bdc227c59d1e1e34f76387d3817d2c0354

commit 570206bdc227c59d1e1e34f76387d3817d2c0354
Author:     Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-05-19 16:53:56 +0000
Commit:     Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-06-17 19:35:25 +0000

    arm64: Enable the floating-point exception traps
    
    To enable it user-space needs to call feenableexcept().
    
    FPE_FLTIDO has been added as the IDF bit can't be mapped to any existing
    FPE code.
    
    Reviewed by:            andrew@
    Differential revision:  https://reviews.freebsd.org/D35247
    MFC after:              2 weeks
    
    (cherry picked from commit 6e2caba7a1297eeda4f43e6377667d2e049f24f9)
---
 sys/arm64/arm64/trap.c     | 32 +++++++++++++++++++++++++++++++-
 sys/arm64/include/armreg.h |  8 ++++++++
 sys/sys/signal.h           |  1 +
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
index 5638bb9f496e..e9afbd47c0af 100644
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -409,6 +409,29 @@ print_registers(struct trapframe *frame)
 	printf("spsr:         %8x\n", frame->tf_spsr);
 }
 
+#ifdef VFP
+static void
+fpe_trap(struct thread *td, void *addr, uint32_t exception)
+{
+	int code;
+
+	code = FPE_FLTIDO;
+	if ((exception & ISS_FP_TFV) != 0) {
+		if ((exception & ISS_FP_IOF) != 0)
+			code = FPE_FLTINV;
+		else if ((exception & ISS_FP_DZF) != 0)
+			code = FPE_FLTDIV;
+		else if ((exception & ISS_FP_OFF) != 0)
+			code = FPE_FLTOVF;
+		else if ((exception & ISS_FP_UFF) != 0)
+			code = FPE_FLTUND;
+		else if ((exception & ISS_FP_IXF) != 0)
+			code = FPE_FLTRES;
+	}
+	call_trapsignal(td, SIGFPE, code, addr, exception);
+}
+#endif
+
 void
 do_el1h_sync(struct thread *td, struct trapframe *frame)
 {
@@ -548,11 +571,18 @@ do_el0_sync(struct thread *td, struct trapframe *frame)
 
 	switch (exception) {
 	case EXCP_FP_SIMD:
-	case EXCP_TRAP_FP:
 #ifdef VFP
 		vfp_restore_state();
 #else
 		panic("VFP exception in userland");
+#endif
+		break;
+	case EXCP_TRAP_FP:
+#ifdef VFP
+		fpe_trap(td, (void *)frame->tf_elr, esr);
+		userret(td, frame);
+#else
+		panic("VFP exception in userland");
 #endif
 		break;
 	case EXCP_SVC32:
diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h
index 8dc517f11a20..e16b17aa4cab 100644
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -179,6 +179,14 @@
 
 /* ESR_ELx */
 #define	ESR_ELx_ISS_MASK	0x01ffffff
+#define	 ISS_FP_TFV_SHIFT	23
+#define	 ISS_FP_TFV		(0x01 << ISS_FP_TFV_SHIFT)
+#define	 ISS_FP_IOF		0x01
+#define	 ISS_FP_DZF		0x02
+#define	 ISS_FP_OFF		0x04
+#define	 ISS_FP_UFF		0x08
+#define	 ISS_FP_IXF		0x10
+#define	 ISS_FP_IDF		0x80
 #define	 ISS_INSN_FnV		(0x01 << 10)
 #define	 ISS_INSN_EA		(0x01 << 9)
 #define	 ISS_INSN_S1PTW		(0x01 << 7)
diff --git a/sys/sys/signal.h b/sys/sys/signal.h
index 8b45a521c3ee..5985ec9e94ee 100644
--- a/sys/sys/signal.h
+++ b/sys/sys/signal.h
@@ -332,6 +332,7 @@ struct siginfo32 {
 #define FPE_FLTRES	6	/* Floating point inexact result.	*/
 #define FPE_FLTINV	7	/* Invalid floating point operation.	*/
 #define FPE_FLTSUB	8	/* Subscript out of range.		*/
+#define FPE_FLTIDO	9	/* Input denormal operation		*/
 
 /* codes for SIGTRAP */
 #define TRAP_BRKPT	1	/* Process breakpoint.			*/