[RFC PATCH 4/4] prctl: Add MIPS IEEE Std 754 compliance mode switching
From: Maciej W. Rozycki
Date: Mon Nov 16 2015 - 09:35:29 EST
Implement the prctl(2) interface for IEEE Std 754 NaN interlinking, as
per "MIPS ABI Extension for IEEE Std 754 Non-Compliant Interlinking"
<https://dmz-portal.mips.com/wiki/MIPS_ABI_-_NaN_Interlinking>:
* interpret the PR_SET_IEEE754_MODE request,
* accept or reject the new mode requested according to FP hardware or
emulator capabilities and any `ieee754=' kernel parameter in effect,
* set the values of the FCSR ABS2008 and NAN2008 bits according to the
NaN encoding requested, either PR_IEEE754_MODE_NAN_LEGACY or
PR_IEEE754_MODE_NAN_2008, if writable,
* on success return bits 31:24 of the auxiliary vector's AT_FLAGS value
corresponding to the new mode in effect, in bits 7:0 of the result.
Signed-off-by: Maciej W. Rozycki <macro@xxxxxxxxxx>
---
linux-mips-nan-interlink-prctl.diff
Index: linux-sfr-test/arch/mips/include/asm/processor.h
===================================================================
--- linux-sfr-test.orig/arch/mips/include/asm/processor.h 2015-11-11 12:34:46.131650000 +0000
+++ linux-sfr-test/arch/mips/include/asm/processor.h 2015-11-11 13:14:09.208745000 +0000
@@ -402,4 +402,13 @@ extern int mips_set_process_fp_mode(stru
#define GET_FP_MODE(task) mips_get_process_fp_mode(task)
#define SET_FP_MODE(task,value) mips_set_process_fp_mode(task, value)
+/*
+ * Likewise the PR_SET_IEEE754_MODE option.
+ */
+extern int mips_set_process_ieee754_mode(struct task_struct *task,
+ unsigned int mode, unsigned int what);
+
+#define SET_IEEE754_MODE(task, mode, what) \
+ mips_set_process_ieee754_mode((task), (mode), (what))
+
#endif /* _ASM_PROCESSOR_H */
Index: linux-sfr-test/arch/mips/kernel/process.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/process.c 2015-11-11 12:34:46.154646000 +0000
+++ linux-sfr-test/arch/mips/kernel/process.c 2015-11-11 13:17:14.564231000 +0000
@@ -9,6 +9,7 @@
* Copyright (C) 2004 Thiemo Seufer
* Copyright (C) 2013 Imagination Technologies Ltd.
*/
+#include <linux/elf.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/tick.h>
@@ -39,7 +40,6 @@
#include <asm/reg.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <asm/elf.h>
#include <asm/isadep.h>
#include <asm/inst.h>
#include <asm/stacktrace.h>
@@ -682,3 +682,76 @@ int mips_set_process_fp_mode(struct task
return 0;
}
+
+/*
+ * Set the process's IEEE 754 compliance mode according to MODE, either
+ * strict or relaxed, affecting WHAT, either legacy or 2008 NaN. On
+ * success return an updated bit pattern as in bits 31:24 of the value
+ * of of of the AT_FLAGS auxiliary vector entry upon program startup,
+ * shifted into bits 7:0 of the result.
+ */
+int mips_set_process_ieee754_mode(struct task_struct *task,
+ unsigned int mode, unsigned int what)
+{
+ struct cpuinfo_mips *c = &boot_cpu_data;
+ struct task_struct *t;
+ bool nan_2008;
+ bool relaxed;
+
+ switch (mode) {
+ case PR_IEEE754_MODE_LEGACY:
+ relaxed = mips_default_ieee754_relaxed;
+ break;
+ case PR_IEEE754_MODE_STRICT:
+ relaxed = false;
+ break;
+ case PR_IEEE754_MODE_RELAXED:
+ if (mips_accept_ieee754_relaxed)
+ relaxed = true;
+ else
+ return -EOPNOTSUPP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ switch (what) {
+ case PR_IEEE754_MODE_NAN_LEGACY:
+ if (relaxed || mips_use_nan_legacy)
+ nan_2008 = false;
+ else
+ return -ENXIO;
+ break;
+ case PR_IEEE754_MODE_NAN_2008:
+ if (relaxed || mips_use_nan_2008)
+ nan_2008 = true;
+ else
+ return -ENXIO;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mips_get_fp_context(task);
+
+ for_each_thread(task, t) {
+ if (relaxed)
+ set_thread_flag(TIF_IEEE754_RELAXED);
+ else
+ clear_thread_flag(TIF_IEEE754_RELAXED);
+ if (nan_2008) {
+ if (!(c->fpu_msk31 & FPU_CSR_NAN2008))
+ t->thread.fpu.fcr31 |= FPU_CSR_NAN2008;
+ if (!(c->fpu_msk31 & FPU_CSR_ABS2008))
+ t->thread.fpu.fcr31 |= FPU_CSR_ABS2008;
+ } else {
+ if (!(c->fpu_msk31 & FPU_CSR_NAN2008))
+ t->thread.fpu.fcr31 &= ~FPU_CSR_NAN2008;
+ if (!(c->fpu_msk31 & FPU_CSR_ABS2008))
+ t->thread.fpu.fcr31 &= ~FPU_CSR_ABS2008;
+ }
+ }
+
+ mips_put_fp_context(task);
+
+ return ELF_FLAGS >> AV_FLAGS_SYSTEM_SHIFT;
+}
Index: linux-sfr-test/include/uapi/linux/prctl.h
===================================================================
--- linux-sfr-test.orig/include/uapi/linux/prctl.h 2015-11-11 12:34:46.157647000 +0000
+++ linux-sfr-test/include/uapi/linux/prctl.h 2015-11-11 13:14:09.286746000 +0000
@@ -197,4 +197,16 @@ struct prctl_mm_map {
# define PR_CAP_AMBIENT_LOWER 3
# define PR_CAP_AMBIENT_CLEAR_ALL 4
+/*
+ * Control MIPS IEEE 754 compliance modes.
+ */
+#define PR_SET_IEEE754_MODE 48
+
+# define PR_IEEE754_MODE_LEGACY 0 /* Legacy mode. */
+# define PR_IEEE754_MODE_STRICT 1 /* Strict mode. */
+# define PR_IEEE754_MODE_RELAXED 2 /* Relaxed mode. */
+
+# define PR_IEEE754_MODE_NAN_LEGACY 0 /* Set legacy NaN encoding. */
+# define PR_IEEE754_MODE_NAN_2008 1 /* Set 2008 NaN encoding. */
+
#endif /* _LINUX_PRCTL_H */
Index: linux-sfr-test/kernel/sys.c
===================================================================
--- linux-sfr-test.orig/kernel/sys.c 2015-11-11 12:34:46.159650000 +0000
+++ linux-sfr-test/kernel/sys.c 2015-11-11 13:14:09.342744000 +0000
@@ -103,6 +103,9 @@
#ifndef SET_FP_MODE
# define SET_FP_MODE(a,b) (-EINVAL)
#endif
+#ifndef SET_IEEE754_MODE
+# define SET_IEEE754_MODE(a, b, c) (-EINVAL)
+#endif
/*
* this is where the system-wide overflow UID and GID are defined, for
@@ -2266,6 +2269,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsi
case PR_GET_FP_MODE:
error = GET_FP_MODE(me);
break;
+ case PR_SET_IEEE754_MODE:
+ error = SET_IEEE754_MODE(me, arg2, arg3);
+ break;
default:
error = -EINVAL;
break;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/