All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/4] MIPS: IEEE Std 754 NaN interlinking support
@ 2015-11-16 14:34 ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:34 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

Hi,

 This implements the kernel part of IEEE Std 754 NaN interlinking support, 
as per "MIPS ABI Extension for IEEE Std 754 Non-Compliant Interlinking" 
<https://dmz-portal.mips.com/wiki/MIPS_ABI_-_NaN_Interlinking>.

 Four patches are included: a pair of preparatory changes, a generic one 
to allow ports to provide their own auxiliary vector's AT_FLAGS entry 
initialiser and one factoring out pieces of FP context maintenance code, 
respectively, and then a pair of actual changes, implementing the NaN 
interlinking feature proper and a prctl(2) interface to switch the 
compliance mode dynamically respectively.

 These patches rely on 2008-NaN support, recently posted, having been 
applied first.

 At this point this is a request for comments only rather than an actual 
patch submission for inclusion, as consensus about the specification has 
to be reached first.  All feedback is welcome on the implementation and 
I'll be happy to address any questions, comments or concerns.

  Maciej



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 0/4] MIPS: IEEE Std 754 NaN interlinking support
@ 2015-11-16 14:34 ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:34 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

Hi,

 This implements the kernel part of IEEE Std 754 NaN interlinking support, 
as per "MIPS ABI Extension for IEEE Std 754 Non-Compliant Interlinking" 
<https://dmz-portal.mips.com/wiki/MIPS_ABI_-_NaN_Interlinking>.

 Four patches are included: a pair of preparatory changes, a generic one 
to allow ports to provide their own auxiliary vector's AT_FLAGS entry 
initialiser and one factoring out pieces of FP context maintenance code, 
respectively, and then a pair of actual changes, implementing the NaN 
interlinking feature proper and a prctl(2) interface to switch the 
compliance mode dynamically respectively.

 These patches rely on 2008-NaN support, recently posted, having been 
applied first.

 At this point this is a request for comments only rather than an actual 
patch submission for inclusion, as consensus about the specification has 
to be reached first.  All feedback is welcome on the implementation and 
I'll be happy to address any questions, comments or concerns.

  Maciej

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 1/4] ELF: Add platform-specific AT_FLAGS initialisation support
@ 2015-11-16 14:34   ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:34 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-elf-at-flags.diff
Index: linux-sfr-test/fs/binfmt_elf.c
===================================================================
--- linux-sfr-test.orig/fs/binfmt_elf.c	2015-09-08 15:24:00.927208000 +0100
+++ linux-sfr-test/fs/binfmt_elf.c	2015-09-08 15:26:10.318310000 +0100
@@ -72,6 +72,10 @@ static int elf_core_dump(struct coredump
 #define ELF_MIN_ALIGN	PAGE_SIZE
 #endif
 
+#ifndef ELF_FLAGS
+#define ELF_FLAGS	0
+#endif
+
 #ifndef ELF_CORE_EFLAGS
 #define ELF_CORE_EFLAGS	0
 #endif
@@ -238,7 +242,7 @@ create_elf_tables(struct linux_binprm *b
 	NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
 	NEW_AUX_ENT(AT_PHNUM, exec->e_phnum);
 	NEW_AUX_ENT(AT_BASE, interp_load_addr);
-	NEW_AUX_ENT(AT_FLAGS, 0);
+	NEW_AUX_ENT(AT_FLAGS, ELF_FLAGS);
 	NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
 	NEW_AUX_ENT(AT_UID, from_kuid_munged(cred->user_ns, cred->uid));
 	NEW_AUX_ENT(AT_EUID, from_kuid_munged(cred->user_ns, cred->euid));
Index: linux-sfr-test/fs/binfmt_elf_fdpic.c
===================================================================
--- linux-sfr-test.orig/fs/binfmt_elf_fdpic.c	2015-09-08 15:24:00.950209000 +0100
+++ linux-sfr-test/fs/binfmt_elf_fdpic.c	2015-09-08 15:29:25.860980000 +0100
@@ -80,6 +80,10 @@ static int elf_fdpic_map_file_by_direct_
 static int elf_fdpic_core_dump(struct coredump_params *cprm);
 #endif
 
+#ifndef ELF_FLAGS
+#define ELF_FLAGS	0
+#endif
+
 static struct linux_binfmt elf_fdpic_format = {
 	.module		= THIS_MODULE,
 	.load_binary	= load_elf_fdpic_binary,
@@ -616,7 +620,7 @@ static int create_elf_fdpic_tables(struc
 	NEW_AUX_ENT(AT_PHENT,	sizeof(struct elf_phdr));
 	NEW_AUX_ENT(AT_PHNUM,	exec_params->hdr.e_phnum);
 	NEW_AUX_ENT(AT_BASE,	interp_params->elfhdr_addr);
-	NEW_AUX_ENT(AT_FLAGS,	0);
+	NEW_AUX_ENT(AT_FLAGS,	ELF_FLAGS);
 	NEW_AUX_ENT(AT_ENTRY,	exec_params->entry_addr);
 	NEW_AUX_ENT(AT_UID,	(elf_addr_t) from_kuid_munged(cred->user_ns, cred->uid));
 	NEW_AUX_ENT(AT_EUID,	(elf_addr_t) from_kuid_munged(cred->user_ns, cred->euid));

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 1/4] ELF: Add platform-specific AT_FLAGS initialisation support
@ 2015-11-16 14:34   ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:34 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-elf-at-flags.diff
Index: linux-sfr-test/fs/binfmt_elf.c
===================================================================
--- linux-sfr-test.orig/fs/binfmt_elf.c	2015-09-08 15:24:00.927208000 +0100
+++ linux-sfr-test/fs/binfmt_elf.c	2015-09-08 15:26:10.318310000 +0100
@@ -72,6 +72,10 @@ static int elf_core_dump(struct coredump
 #define ELF_MIN_ALIGN	PAGE_SIZE
 #endif
 
+#ifndef ELF_FLAGS
+#define ELF_FLAGS	0
+#endif
+
 #ifndef ELF_CORE_EFLAGS
 #define ELF_CORE_EFLAGS	0
 #endif
@@ -238,7 +242,7 @@ create_elf_tables(struct linux_binprm *b
 	NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
 	NEW_AUX_ENT(AT_PHNUM, exec->e_phnum);
 	NEW_AUX_ENT(AT_BASE, interp_load_addr);
-	NEW_AUX_ENT(AT_FLAGS, 0);
+	NEW_AUX_ENT(AT_FLAGS, ELF_FLAGS);
 	NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
 	NEW_AUX_ENT(AT_UID, from_kuid_munged(cred->user_ns, cred->uid));
 	NEW_AUX_ENT(AT_EUID, from_kuid_munged(cred->user_ns, cred->euid));
Index: linux-sfr-test/fs/binfmt_elf_fdpic.c
===================================================================
--- linux-sfr-test.orig/fs/binfmt_elf_fdpic.c	2015-09-08 15:24:00.950209000 +0100
+++ linux-sfr-test/fs/binfmt_elf_fdpic.c	2015-09-08 15:29:25.860980000 +0100
@@ -80,6 +80,10 @@ static int elf_fdpic_map_file_by_direct_
 static int elf_fdpic_core_dump(struct coredump_params *cprm);
 #endif
 
+#ifndef ELF_FLAGS
+#define ELF_FLAGS	0
+#endif
+
 static struct linux_binfmt elf_fdpic_format = {
 	.module		= THIS_MODULE,
 	.load_binary	= load_elf_fdpic_binary,
@@ -616,7 +620,7 @@ static int create_elf_fdpic_tables(struc
 	NEW_AUX_ENT(AT_PHENT,	sizeof(struct elf_phdr));
 	NEW_AUX_ENT(AT_PHNUM,	exec_params->hdr.e_phnum);
 	NEW_AUX_ENT(AT_BASE,	interp_params->elfhdr_addr);
-	NEW_AUX_ENT(AT_FLAGS,	0);
+	NEW_AUX_ENT(AT_FLAGS,	ELF_FLAGS);
 	NEW_AUX_ENT(AT_ENTRY,	exec_params->entry_addr);
 	NEW_AUX_ENT(AT_UID,	(elf_addr_t) from_kuid_munged(cred->user_ns, cred->uid));
 	NEW_AUX_ENT(AT_EUID,	(elf_addr_t) from_kuid_munged(cred->user_ns, cred->euid));

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 2/4] MIPS: Factor out FP context preemption
@ 2015-11-16 14:34   ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:34 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
Following the discussion around commit 9791554b [MIPS,prctl: add 
PR_[GS]ET_FP_MODE prctl options for MIPS] or 
<http://patchwork.linux-mips.org/patch/8899/> and Leonid's observation 
<http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=54B02115.7090609%40imgtec.com> 
in particular, I agree this would best be done with an IPI, however such 
an improvement is independent of the changes made as a part of this series 
so I took the minimal approach and left the solution implemented so far 
unchanged.  Especially as Leonid says he's got a patch already available.

linux-mips-process-fp-context.diff
Index: linux-sfr-test/arch/mips/kernel/process.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/process.c	2015-11-13 00:36:09.885716000 +0000
+++ linux-sfr-test/arch/mips/kernel/process.c	2015-11-16 13:50:18.962058000 +0000
@@ -570,6 +570,60 @@ void arch_trigger_all_cpu_backtrace(bool
 	smp_call_function(arch_dump_stack, NULL, 1);
 }
 
+/*
+ * Make the FP context available for mode changes.
+ */
+static void mips_get_fp_context(struct task_struct *task)
+{
+	unsigned long switch_count;
+	struct task_struct *t;
+
+	/* Save FP & vector context, then disable FPU & MSA.  */
+	if (task->signal == current->signal)
+		lose_fpu(1);
+
+	/* Prevent any threads from obtaining live FP context.  */
+	atomic_set(&task->mm->context.fp_mode_switching, 1);
+	smp_mb__after_atomic();
+
+	/*
+	 * If there are multiple online CPUs then wait until all threads
+	 * whose FP mode is about to change have been context switched.
+	 * This approach allows us to only worry about whether an FP mode
+	 * switch is in progress when FP is first used in a tasks time
+	 * slice.  Pretty much all of the mode switch overhead can thus
+	 * be confined to cases where mode switches are actually occurring.
+	 * That is, to here.  However for the thread performing the mode
+	 * switch it may take a while...
+	 */
+	if (num_online_cpus() > 1) {
+		spin_lock_irq(&task->sighand->siglock);
+
+		for_each_thread(task, t) {
+			if (t == current)
+				continue;
+
+			switch_count = t->nvcsw + t->nivcsw;
+
+			do {
+				spin_unlock_irq(&task->sighand->siglock);
+				cond_resched();
+				spin_lock_irq(&task->sighand->siglock);
+			} while ((t->nvcsw + t->nivcsw) == switch_count);
+		}
+
+		spin_unlock_irq(&task->sighand->siglock);
+	}
+}
+
+/*
+ * Allow threads to use FP again.
+ */
+static void mips_put_fp_context(struct task_struct *task)
+{
+	atomic_set(&task->mm->context.fp_mode_switching, 0);
+}
+
 int mips_get_process_fp_mode(struct task_struct *task)
 {
 	int value = 0;
@@ -585,7 +639,6 @@ int mips_get_process_fp_mode(struct task
 int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 {
 	const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE;
-	unsigned long switch_count;
 	struct task_struct *t;
 
 	/* Check the value is valid */
@@ -603,41 +656,7 @@ int mips_set_process_fp_mode(struct task
 	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
 		return -EOPNOTSUPP;
 
-	/* Save FP & vector context, then disable FPU & MSA */
-	if (task->signal == current->signal)
-		lose_fpu(1);
-
-	/* Prevent any threads from obtaining live FP context */
-	atomic_set(&task->mm->context.fp_mode_switching, 1);
-	smp_mb__after_atomic();
-
-	/*
-	 * If there are multiple online CPUs then wait until all threads whose
-	 * FP mode is about to change have been context switched. This approach
-	 * allows us to only worry about whether an FP mode switch is in
-	 * progress when FP is first used in a tasks time slice. Pretty much all
-	 * of the mode switch overhead can thus be confined to cases where mode
-	 * switches are actually occuring. That is, to here. However for the
-	 * thread performing the mode switch it may take a while...
-	 */
-	if (num_online_cpus() > 1) {
-		spin_lock_irq(&task->sighand->siglock);
-
-		for_each_thread(task, t) {
-			if (t == current)
-				continue;
-
-			switch_count = t->nvcsw + t->nivcsw;
-
-			do {
-				spin_unlock_irq(&task->sighand->siglock);
-				cond_resched();
-				spin_lock_irq(&task->sighand->siglock);
-			} while ((t->nvcsw + t->nivcsw) == switch_count);
-		}
-
-		spin_unlock_irq(&task->sighand->siglock);
-	}
+	mips_get_fp_context(task);
 
 	/*
 	 * There are now no threads of the process with live FP context, so it
@@ -659,8 +678,7 @@ int mips_set_process_fp_mode(struct task
 			clear_tsk_thread_flag(t, TIF_HYBRID_FPREGS);
 	}
 
-	/* Allow threads to use FP again */
-	atomic_set(&task->mm->context.fp_mode_switching, 0);
+	mips_put_fp_context(task);
 
 	return 0;
 }

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 2/4] MIPS: Factor out FP context preemption
@ 2015-11-16 14:34   ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:34 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
Following the discussion around commit 9791554b [MIPS,prctl: add 
PR_[GS]ET_FP_MODE prctl options for MIPS] or 
<http://patchwork.linux-mips.org/patch/8899/> and Leonid's observation 
<http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=54B02115.7090609%40imgtec.com> 
in particular, I agree this would best be done with an IPI, however such 
an improvement is independent of the changes made as a part of this series 
so I took the minimal approach and left the solution implemented so far 
unchanged.  Especially as Leonid says he's got a patch already available.

linux-mips-process-fp-context.diff
Index: linux-sfr-test/arch/mips/kernel/process.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/process.c	2015-11-13 00:36:09.885716000 +0000
+++ linux-sfr-test/arch/mips/kernel/process.c	2015-11-16 13:50:18.962058000 +0000
@@ -570,6 +570,60 @@ void arch_trigger_all_cpu_backtrace(bool
 	smp_call_function(arch_dump_stack, NULL, 1);
 }
 
+/*
+ * Make the FP context available for mode changes.
+ */
+static void mips_get_fp_context(struct task_struct *task)
+{
+	unsigned long switch_count;
+	struct task_struct *t;
+
+	/* Save FP & vector context, then disable FPU & MSA.  */
+	if (task->signal == current->signal)
+		lose_fpu(1);
+
+	/* Prevent any threads from obtaining live FP context.  */
+	atomic_set(&task->mm->context.fp_mode_switching, 1);
+	smp_mb__after_atomic();
+
+	/*
+	 * If there are multiple online CPUs then wait until all threads
+	 * whose FP mode is about to change have been context switched.
+	 * This approach allows us to only worry about whether an FP mode
+	 * switch is in progress when FP is first used in a tasks time
+	 * slice.  Pretty much all of the mode switch overhead can thus
+	 * be confined to cases where mode switches are actually occurring.
+	 * That is, to here.  However for the thread performing the mode
+	 * switch it may take a while...
+	 */
+	if (num_online_cpus() > 1) {
+		spin_lock_irq(&task->sighand->siglock);
+
+		for_each_thread(task, t) {
+			if (t == current)
+				continue;
+
+			switch_count = t->nvcsw + t->nivcsw;
+
+			do {
+				spin_unlock_irq(&task->sighand->siglock);
+				cond_resched();
+				spin_lock_irq(&task->sighand->siglock);
+			} while ((t->nvcsw + t->nivcsw) == switch_count);
+		}
+
+		spin_unlock_irq(&task->sighand->siglock);
+	}
+}
+
+/*
+ * Allow threads to use FP again.
+ */
+static void mips_put_fp_context(struct task_struct *task)
+{
+	atomic_set(&task->mm->context.fp_mode_switching, 0);
+}
+
 int mips_get_process_fp_mode(struct task_struct *task)
 {
 	int value = 0;
@@ -585,7 +639,6 @@ int mips_get_process_fp_mode(struct task
 int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
 {
 	const unsigned int known_bits = PR_FP_MODE_FR | PR_FP_MODE_FRE;
-	unsigned long switch_count;
 	struct task_struct *t;
 
 	/* Check the value is valid */
@@ -603,41 +656,7 @@ int mips_set_process_fp_mode(struct task
 	if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
 		return -EOPNOTSUPP;
 
-	/* Save FP & vector context, then disable FPU & MSA */
-	if (task->signal == current->signal)
-		lose_fpu(1);
-
-	/* Prevent any threads from obtaining live FP context */
-	atomic_set(&task->mm->context.fp_mode_switching, 1);
-	smp_mb__after_atomic();
-
-	/*
-	 * If there are multiple online CPUs then wait until all threads whose
-	 * FP mode is about to change have been context switched. This approach
-	 * allows us to only worry about whether an FP mode switch is in
-	 * progress when FP is first used in a tasks time slice. Pretty much all
-	 * of the mode switch overhead can thus be confined to cases where mode
-	 * switches are actually occuring. That is, to here. However for the
-	 * thread performing the mode switch it may take a while...
-	 */
-	if (num_online_cpus() > 1) {
-		spin_lock_irq(&task->sighand->siglock);
-
-		for_each_thread(task, t) {
-			if (t == current)
-				continue;
-
-			switch_count = t->nvcsw + t->nivcsw;
-
-			do {
-				spin_unlock_irq(&task->sighand->siglock);
-				cond_resched();
-				spin_lock_irq(&task->sighand->siglock);
-			} while ((t->nvcsw + t->nivcsw) == switch_count);
-		}
-
-		spin_unlock_irq(&task->sighand->siglock);
-	}
+	mips_get_fp_context(task);
 
 	/*
 	 * There are now no threads of the process with live FP context, so it
@@ -659,8 +678,7 @@ int mips_set_process_fp_mode(struct task
 			clear_tsk_thread_flag(t, TIF_HYBRID_FPREGS);
 	}
 
-	/* Allow threads to use FP again */
-	atomic_set(&task->mm->context.fp_mode_switching, 0);
+	mips_put_fp_context(task);
 
 	return 0;
 }

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 3/4] MIPS: Implement IEEE Std 754 NaN interlinking support
@ 2015-11-16 14:35   ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:35 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

Implement the kernel part of IEEE Std 754 NaN interlinking support, as 
per "MIPS ABI Extension for IEEE Std 754 Non-Compliant Interlinking" 
<https://dmz-portal.mips.com/wiki/MIPS_ABI_-_NaN_Interlinking>:

* interpret the MIPS_AFL_FLAGS1_IEEE and MIPS_AFL_FLAGS2_RELAXED flags 
  in PT_MIPS_ABIFLAGS,

* accept or reject ELF binaries and interpreters accordingly,

* initialise auxiliary vector's AT_FLAGS appropriately,

* suppress Invalid Operation exceptions with operations on sNaN data.

Add a `strictest' setting to the `ieee754=' kernel parameter to enforce 
a full IEEE Std 754 conformance and reject any binaries which request 
the relaxed NaN encoding mode.  Update documentation accordingly.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-mips-nan-interlink.diff
Index: linux-sfr-test/Documentation/kernel-parameters.txt
===================================================================
--- linux-sfr-test.orig/Documentation/kernel-parameters.txt	2015-11-11 02:21:08.155578000 +0000
+++ linux-sfr-test/Documentation/kernel-parameters.txt	2015-11-11 12:22:51.732826000 +0000
@@ -1400,7 +1400,8 @@ bytes respectively. Such letter suffixes
 			idle=nomwait: Disable mwait for CPU C-states
 
 	ieee754=	[MIPS] Select IEEE Std 754 conformance mode
-			Format: { strict | legacy | 2008 | relaxed }
+			Format: { strictest | strict | best | legacy | 2008 |
+				  relaxed }
 			Default: strict
 
 			Choose which programs will be accepted for execution
@@ -1412,23 +1413,30 @@ bytes respectively. Such letter suffixes
 			encoding mode.
 
 			Available settings are as follows:
-			strict	accept binaries that request a NaN encoding
-				supported by the FPU
-			legacy	only accept legacy-NaN binaries, if supported
-				by the FPU
-			2008	only accept 2008-NaN binaries, if supported
-				by the FPU
-			relaxed	accept any binaries regardless of whether
-				supported by the FPU
+			strictest	require binaries to request a NaN
+					encoding supported by the FPU, reject
+					binaries that request the relaxed NaN
+					encoding mode
+			strict		accept binaries that request a NaN
+					encoding supported by the FPU
+			best		accept binaries that request a NaN
+					encoding supported by the FPU or all
+					on the emulator
+			legacy		only accept legacy-NaN binaries, if
+					supported by the FPU
+			2008		only accept 2008-NaN binaries, if
+					supported by the FPU
+			relaxed		accept any binaries regardless of
+					whether supported by the FPU
 
 			The FPU emulator is always able to support both NaN
-			encodings, so if no FPU hardware is present or it has
-			been disabled with 'nofpu', then the settings of
+			encodings, so if no FPU hardware is present or it
+			has been disabled with 'nofpu', then the settings of
 			'legacy' and '2008' strap the emulator accordingly,
-			'relaxed' straps the emulator for both legacy-NaN and
-			2008-NaN, whereas 'strict' enables legacy-NaN only on
-			legacy processors and both NaN encodings on MIPS32 or
-			MIPS64 CPUs.
+			'best' and 'relaxed' strap the emulator for both
+			legacy-NaN and 2008-NaN, whereas 'strictest' and
+			'strict' enable legacy-NaN only on legacy processors
+			and both NaN encodings on MIPS32 or MIPS64 CPUs.
 
 			The setting for ABS.fmt/NEG.fmt instruction execution
 			mode generally follows that for the NaN encoding,
Index: linux-sfr-test/arch/mips/include/asm/elf.h
===================================================================
--- linux-sfr-test.orig/arch/mips/include/asm/elf.h	2015-11-11 02:21:08.158574000 +0000
+++ linux-sfr-test/arch/mips/include/asm/elf.h	2015-11-11 12:23:55.325343000 +0000
@@ -170,6 +170,13 @@
 #define SHF_MIPS_NAMES		0x02000000
 #define SHF_MIPS_NODUPES	0x01000000
 
+/* AT_FLAGS bits 31:24 are reserved for system semantics in the MIPS psABI.  */
+#define AV_FLAGS_SYSTEM_SHIFT	24
+
+/* MIPS/Linux system AT_FLAGS bits.  */
+#define AV_FLAGS_MIPS_RELAXED	(1U << (AV_FLAGS_SYSTEM_SHIFT + 1))
+						/* Relaxed IEEE 754 mode.  */
+
 #ifndef ELF_ARCH
 /* ELF register definitions */
 #define ELF_NGREG	45
@@ -205,6 +212,14 @@ struct mips_elf_abiflags_v0 {
 #define MIPS_ABI_FP_64		6	/* -mips32r2 -mfp64 */
 #define MIPS_ABI_FP_64A		7	/* -mips32r2 -mfp64 -mno-odd-spreg */
 
+/* Masks for `flags1'.  */
+/* IEEE Std 754 compliance mode selection requested.  */
+#define MIPS_AFL_FLAGS1_IEEE	(1U << 1)
+
+/* Masks for `flags2'.  */
+/* IEEE Std 754 relaxed compliance mode selected.  */
+#define MIPS_AFL_FLAGS2_RELAXED	(1U << 1)
+
 #ifdef CONFIG_32BIT
 
 /*
@@ -379,6 +394,18 @@ do {									\
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
+/* Platform-specific informational flags.  */
+
+#define ELF_FLAGS							\
+({									\
+	elf_addr_t at_flags = 0;					\
+									\
+	if (test_thread_flag(TIF_IEEE754_RELAXED))			\
+		at_flags |= AV_FLAGS_MIPS_RELAXED;			\
+									\
+	at_flags;							\
+})
+
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports.  This could be done in userspace,
    but it's not easy, and we've already done it here.  */
@@ -436,21 +463,31 @@ struct arch_elf_state {
 	int fp_abi;
 	int interp_fp_abi;
 	int overall_fp_mode;
+	bool ieee754_relaxed;
+	bool interp_ieee754_relaxed;
 };
 
 #define MIPS_ABI_FP_UNKNOWN	(-1)	/* Unknown FP ABI (kernel internal) */
 
-#define INIT_ARCH_ELF_STATE {			\
-	.nan_2008 = -1,				\
-	.fp_abi = MIPS_ABI_FP_UNKNOWN,		\
-	.interp_fp_abi = MIPS_ABI_FP_UNKNOWN,	\
-	.overall_fp_mode = -1,			\
+#define INIT_ARCH_ELF_STATE {						\
+	.nan_2008 = -1,							\
+	.fp_abi = MIPS_ABI_FP_UNKNOWN,					\
+	.interp_fp_abi = MIPS_ABI_FP_UNKNOWN,				\
+	.overall_fp_mode = -1,						\
+	.ieee754_relaxed = mips_default_ieee754_relaxed,		\
+	.interp_ieee754_relaxed = false,				\
 }
 
 /* Whether to accept legacy-NaN and 2008-NaN user binaries.  */
 extern bool mips_use_nan_legacy;
 extern bool mips_use_nan_2008;
 
+/* Whether to select the IEEE Std 754 relaxed compliance mode by default.  */
+extern bool mips_default_ieee754_relaxed;
+
+/* Whether to accept IEEE Std 754 relaxed compliance mode binaries.  */
+extern bool mips_accept_ieee754_relaxed;
+
 extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
 			    bool is_interp, struct arch_elf_state *state);
 
Index: linux-sfr-test/arch/mips/include/asm/thread_info.h
===================================================================
--- linux-sfr-test.orig/arch/mips/include/asm/thread_info.h	2015-11-11 02:21:08.160573000 +0000
+++ linux-sfr-test/arch/mips/include/asm/thread_info.h	2015-11-11 12:22:51.855825000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 #define TIF_UPROBE		6	/* breakpointed or singlestepping */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
+#define TIF_IEEE754_RELAXED	17	/* Relaxed IEEE Std 754 rules */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_NOHZ		19	/* in adaptive nohz mode */
 #define TIF_FIXADE		20	/* Fix address errors in software */
Index: linux-sfr-test/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/cpu-probe.c	2015-11-11 02:21:08.161578000 +0000
+++ linux-sfr-test/arch/mips/kernel/cpu-probe.c	2015-11-11 12:22:51.859824000 +0000
@@ -154,13 +154,15 @@ static void cpu_set_fpu_2008(struct cpui
  * IEEE 754 conformance mode to use.  Affects the NaN encoding and the
  * ABS.fmt/NEG.fmt execution mode.
  */
-static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT;
+static enum {
+	STRICTEST, STRICT, BEST, LEGACY, STD2008, RELAXED
+} ieee754 = STRICT;
 
 /*
  * Set the IEEE 754 NaN encodings and the ABS.fmt/NEG.fmt execution modes
  * to support by the FPU emulator according to the IEEE 754 conformance
- * mode selected.  Note that "relaxed" straps the emulator so that it
- * allows 2008-NaN binaries even for legacy processors.
+ * mode selected.  Note that "best" and "relaxed" strap the emulator so
+ * that it allows 2008-NaN binaries even for legacy processors.
  */
 static void cpu_set_nofpu_2008(struct cpuinfo_mips *c)
 {
@@ -169,6 +171,7 @@ static void cpu_set_nofpu_2008(struct cp
 	c->fpu_msk31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
 
 	switch (ieee754) {
+	case STRICTEST:
 	case STRICT:
 		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
 				    MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
@@ -179,6 +182,9 @@ static void cpu_set_nofpu_2008(struct cp
 			c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
 		}
 		break;
+	case BEST:
+		c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY;
+		break;
 	case LEGACY:
 		c->options |= MIPS_CPU_NAN_LEGACY;
 		c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
@@ -200,8 +206,13 @@ static void cpu_set_nofpu_2008(struct cp
  */
 static void cpu_set_nan_2008(struct cpuinfo_mips *c)
 {
+	mips_default_ieee754_relaxed = ieee754 == RELAXED;
+	mips_accept_ieee754_relaxed = ieee754 != STRICTEST;
+
 	switch (ieee754) {
+	case STRICTEST:
 	case STRICT:
+	case BEST:
 		mips_use_nan_legacy = !!cpu_has_nan_legacy;
 		mips_use_nan_2008 = !!cpu_has_nan_2008;
 		break;
@@ -224,17 +235,23 @@ static void cpu_set_nan_2008(struct cpui
  * IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode override
  * settings:
  *
- * strict:  accept binaries that request a NaN encoding supported by the FPU
- * legacy:  only accept legacy-NaN binaries
- * 2008:    only accept 2008-NaN binaries
- * relaxed: accept any binaries regardless of whether supported by the FPU
+ * strictest: require binaries to request a NaN encoding supported by the FPU
+ * strict:    accept binaries that request a NaN encoding supported by the FPU
+ * best:      accept all binaries in full FP emulation, otherwise like "strict"
+ * legacy:    only accept legacy-NaN binaries
+ * 2008:      only accept 2008-NaN binaries
+ * relaxed:   accept any binaries regardless of whether supported by the FPU
  */
 static int __init ieee754_setup(char *s)
 {
 	if (!s)
 		return -1;
+	else if (!strcmp(s, "strictest"))
+		ieee754 = STRICTEST;
 	else if (!strcmp(s, "strict"))
 		ieee754 = STRICT;
+	else if (!strcmp(s, "best"))
+		ieee754 = BEST;
 	else if (!strcmp(s, "legacy"))
 		ieee754 = LEGACY;
 	else if (!strcmp(s, "2008"))
Index: linux-sfr-test/arch/mips/kernel/elf.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/elf.c	2015-11-11 02:21:08.163575000 +0000
+++ linux-sfr-test/arch/mips/kernel/elf.c	2015-11-11 12:22:51.861832000 +0000
@@ -17,6 +17,12 @@
 bool mips_use_nan_legacy;
 bool mips_use_nan_2008;
 
+/* Whether to select the IEEE Std 754 relaxed compliance mode by default.  */
+bool mips_default_ieee754_relaxed;
+
+/* Whether to accept IEEE Std 754 relaxed compliance mode binaries.  */
+bool mips_accept_ieee754_relaxed;
+
 /* FPU modes */
 enum {
 	FP_FRE,
@@ -81,6 +87,7 @@ int arch_elf_pt_proc(void *_ehdr, void *
 	struct elf32_phdr *phdr32 = _phdr;
 	struct elf64_phdr *phdr64 = _phdr;
 	struct mips_elf_abiflags_v0 abiflags;
+	bool relaxed;
 	bool elf32;
 	u32 flags;
 	int ret;
@@ -131,6 +138,17 @@ int arch_elf_pt_proc(void *_ehdr, void *
 	else
 		state->fp_abi = abiflags.fp_abi;
 
+	/* Record any requested IEEE Std 754 compliance mode.  */
+	relaxed = !!(abiflags.flags2 & MIPS_AFL_FLAGS2_RELAXED);
+	if (abiflags.flags1 & MIPS_AFL_FLAGS1_IEEE) {
+		if (is_interp)
+			state->interp_ieee754_relaxed = relaxed;
+		else
+			state->ieee754_relaxed = relaxed;
+	} else if (relaxed) {
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -147,6 +165,7 @@ int arch_check_elf(void *_ehdr, bool has
 	} *iehdr = _interp_ehdr;
 	struct mode_req prog_req, interp_req;
 	int fp_abi, interp_fp_abi, abi0, abi1, max_abi;
+	bool relaxed;
 	bool elf32;
 	u32 flags;
 
@@ -155,23 +174,31 @@ int arch_check_elf(void *_ehdr, bool has
 
 	/*
 	 * Determine the NaN personality, reject the binary if not allowed.
-	 * Also ensure that any interpreter matches the executable.
+	 * Check hardware support if strict conformance requested by the
+	 * binary, otherwise respect any kernel override.  Also ensure that
+	 * any interpreter matches the executable.
 	 */
+	relaxed = state->ieee754_relaxed;
+	if (relaxed && !mips_accept_ieee754_relaxed)
+		return -ENOEXEC;
 	if (flags & EF_MIPS_NAN2008) {
-		if (mips_use_nan_2008)
-			state->nan_2008 = 1;
+		if (relaxed || mips_use_nan_2008)
+			state->nan_2008 = mips_use_nan_2008;
 		else
 			return -ENOEXEC;
 	} else {
-		if (mips_use_nan_legacy)
-			state->nan_2008 = 0;
+		if (relaxed || mips_use_nan_legacy)
+			state->nan_2008 = !mips_use_nan_legacy;
 		else
 			return -ENOEXEC;
 	}
-	if (has_interpreter) {
+	if (has_interpreter && !relaxed) {
 		bool ielf32;
 		u32 iflags;
 
+		if (state->interp_ieee754_relaxed)
+			return -ELIBBAD;
+
 		ielf32 = iehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
 		iflags = ielf32 ? iehdr->e32.e_flags : iehdr->e64.e_flags;
 
@@ -312,6 +339,11 @@ void mips_set_personality_nan(struct arc
 	struct cpuinfo_mips *c = &boot_cpu_data;
 	struct task_struct *t = current;
 
+	if (state->ieee754_relaxed)
+		set_thread_flag(TIF_IEEE754_RELAXED);
+	else
+		clear_thread_flag(TIF_IEEE754_RELAXED);
+
 	t->thread.fpu.fcr31 = c->fpu_csr31;
 	switch (state->nan_2008) {
 	case 0:
Index: linux-sfr-test/arch/mips/math-emu/ieee754dp.c
===================================================================
--- linux-sfr-test.orig/arch/mips/math-emu/ieee754dp.c	2015-11-11 02:21:08.165573000 +0000
+++ linux-sfr-test/arch/mips/math-emu/ieee754dp.c	2015-11-11 12:22:51.884826000 +0000
@@ -53,7 +53,8 @@ union ieee754dp __cold ieee754dp_nanxcpt
 {
 	assert(ieee754dp_issnan(r));
 
-	ieee754_setcx(IEEE754_INVALID_OPERATION);
+	if (!test_thread_flag(TIF_IEEE754_RELAXED))
+		ieee754_setcx(IEEE754_INVALID_OPERATION);
 	if (ieee754_csr.nan2008) {
 		DPMANT(r) |= DP_MBIT(DP_FBITS - 1);
 	} else {
Index: linux-sfr-test/arch/mips/math-emu/ieee754sp.c
===================================================================
--- linux-sfr-test.orig/arch/mips/math-emu/ieee754sp.c	2015-11-11 02:21:08.167574000 +0000
+++ linux-sfr-test/arch/mips/math-emu/ieee754sp.c	2015-11-11 12:22:51.887824000 +0000
@@ -53,7 +53,8 @@ union ieee754sp __cold ieee754sp_nanxcpt
 {
 	assert(ieee754sp_issnan(r));
 
-	ieee754_setcx(IEEE754_INVALID_OPERATION);
+	if (!test_thread_flag(TIF_IEEE754_RELAXED))
+		ieee754_setcx(IEEE754_INVALID_OPERATION);
 	if (ieee754_csr.nan2008) {
 		SPMANT(r) |= SP_MBIT(SP_FBITS - 1);
 	} else {

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 3/4] MIPS: Implement IEEE Std 754 NaN interlinking support
@ 2015-11-16 14:35   ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:35 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

Implement the kernel part of IEEE Std 754 NaN interlinking support, as 
per "MIPS ABI Extension for IEEE Std 754 Non-Compliant Interlinking" 
<https://dmz-portal.mips.com/wiki/MIPS_ABI_-_NaN_Interlinking>:

* interpret the MIPS_AFL_FLAGS1_IEEE and MIPS_AFL_FLAGS2_RELAXED flags 
  in PT_MIPS_ABIFLAGS,

* accept or reject ELF binaries and interpreters accordingly,

* initialise auxiliary vector's AT_FLAGS appropriately,

* suppress Invalid Operation exceptions with operations on sNaN data.

Add a `strictest' setting to the `ieee754=' kernel parameter to enforce 
a full IEEE Std 754 conformance and reject any binaries which request 
the relaxed NaN encoding mode.  Update documentation accordingly.

Signed-off-by: Maciej W. Rozycki <macro@imgtec.com>
---
linux-mips-nan-interlink.diff
Index: linux-sfr-test/Documentation/kernel-parameters.txt
===================================================================
--- linux-sfr-test.orig/Documentation/kernel-parameters.txt	2015-11-11 02:21:08.155578000 +0000
+++ linux-sfr-test/Documentation/kernel-parameters.txt	2015-11-11 12:22:51.732826000 +0000
@@ -1400,7 +1400,8 @@ bytes respectively. Such letter suffixes
 			idle=nomwait: Disable mwait for CPU C-states
 
 	ieee754=	[MIPS] Select IEEE Std 754 conformance mode
-			Format: { strict | legacy | 2008 | relaxed }
+			Format: { strictest | strict | best | legacy | 2008 |
+				  relaxed }
 			Default: strict
 
 			Choose which programs will be accepted for execution
@@ -1412,23 +1413,30 @@ bytes respectively. Such letter suffixes
 			encoding mode.
 
 			Available settings are as follows:
-			strict	accept binaries that request a NaN encoding
-				supported by the FPU
-			legacy	only accept legacy-NaN binaries, if supported
-				by the FPU
-			2008	only accept 2008-NaN binaries, if supported
-				by the FPU
-			relaxed	accept any binaries regardless of whether
-				supported by the FPU
+			strictest	require binaries to request a NaN
+					encoding supported by the FPU, reject
+					binaries that request the relaxed NaN
+					encoding mode
+			strict		accept binaries that request a NaN
+					encoding supported by the FPU
+			best		accept binaries that request a NaN
+					encoding supported by the FPU or all
+					on the emulator
+			legacy		only accept legacy-NaN binaries, if
+					supported by the FPU
+			2008		only accept 2008-NaN binaries, if
+					supported by the FPU
+			relaxed		accept any binaries regardless of
+					whether supported by the FPU
 
 			The FPU emulator is always able to support both NaN
-			encodings, so if no FPU hardware is present or it has
-			been disabled with 'nofpu', then the settings of
+			encodings, so if no FPU hardware is present or it
+			has been disabled with 'nofpu', then the settings of
 			'legacy' and '2008' strap the emulator accordingly,
-			'relaxed' straps the emulator for both legacy-NaN and
-			2008-NaN, whereas 'strict' enables legacy-NaN only on
-			legacy processors and both NaN encodings on MIPS32 or
-			MIPS64 CPUs.
+			'best' and 'relaxed' strap the emulator for both
+			legacy-NaN and 2008-NaN, whereas 'strictest' and
+			'strict' enable legacy-NaN only on legacy processors
+			and both NaN encodings on MIPS32 or MIPS64 CPUs.
 
 			The setting for ABS.fmt/NEG.fmt instruction execution
 			mode generally follows that for the NaN encoding,
Index: linux-sfr-test/arch/mips/include/asm/elf.h
===================================================================
--- linux-sfr-test.orig/arch/mips/include/asm/elf.h	2015-11-11 02:21:08.158574000 +0000
+++ linux-sfr-test/arch/mips/include/asm/elf.h	2015-11-11 12:23:55.325343000 +0000
@@ -170,6 +170,13 @@
 #define SHF_MIPS_NAMES		0x02000000
 #define SHF_MIPS_NODUPES	0x01000000
 
+/* AT_FLAGS bits 31:24 are reserved for system semantics in the MIPS psABI.  */
+#define AV_FLAGS_SYSTEM_SHIFT	24
+
+/* MIPS/Linux system AT_FLAGS bits.  */
+#define AV_FLAGS_MIPS_RELAXED	(1U << (AV_FLAGS_SYSTEM_SHIFT + 1))
+						/* Relaxed IEEE 754 mode.  */
+
 #ifndef ELF_ARCH
 /* ELF register definitions */
 #define ELF_NGREG	45
@@ -205,6 +212,14 @@ struct mips_elf_abiflags_v0 {
 #define MIPS_ABI_FP_64		6	/* -mips32r2 -mfp64 */
 #define MIPS_ABI_FP_64A		7	/* -mips32r2 -mfp64 -mno-odd-spreg */
 
+/* Masks for `flags1'.  */
+/* IEEE Std 754 compliance mode selection requested.  */
+#define MIPS_AFL_FLAGS1_IEEE	(1U << 1)
+
+/* Masks for `flags2'.  */
+/* IEEE Std 754 relaxed compliance mode selected.  */
+#define MIPS_AFL_FLAGS2_RELAXED	(1U << 1)
+
 #ifdef CONFIG_32BIT
 
 /*
@@ -379,6 +394,18 @@ do {									\
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
+/* Platform-specific informational flags.  */
+
+#define ELF_FLAGS							\
+({									\
+	elf_addr_t at_flags = 0;					\
+									\
+	if (test_thread_flag(TIF_IEEE754_RELAXED))			\
+		at_flags |= AV_FLAGS_MIPS_RELAXED;			\
+									\
+	at_flags;							\
+})
+
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports.  This could be done in userspace,
    but it's not easy, and we've already done it here.  */
@@ -436,21 +463,31 @@ struct arch_elf_state {
 	int fp_abi;
 	int interp_fp_abi;
 	int overall_fp_mode;
+	bool ieee754_relaxed;
+	bool interp_ieee754_relaxed;
 };
 
 #define MIPS_ABI_FP_UNKNOWN	(-1)	/* Unknown FP ABI (kernel internal) */
 
-#define INIT_ARCH_ELF_STATE {			\
-	.nan_2008 = -1,				\
-	.fp_abi = MIPS_ABI_FP_UNKNOWN,		\
-	.interp_fp_abi = MIPS_ABI_FP_UNKNOWN,	\
-	.overall_fp_mode = -1,			\
+#define INIT_ARCH_ELF_STATE {						\
+	.nan_2008 = -1,							\
+	.fp_abi = MIPS_ABI_FP_UNKNOWN,					\
+	.interp_fp_abi = MIPS_ABI_FP_UNKNOWN,				\
+	.overall_fp_mode = -1,						\
+	.ieee754_relaxed = mips_default_ieee754_relaxed,		\
+	.interp_ieee754_relaxed = false,				\
 }
 
 /* Whether to accept legacy-NaN and 2008-NaN user binaries.  */
 extern bool mips_use_nan_legacy;
 extern bool mips_use_nan_2008;
 
+/* Whether to select the IEEE Std 754 relaxed compliance mode by default.  */
+extern bool mips_default_ieee754_relaxed;
+
+/* Whether to accept IEEE Std 754 relaxed compliance mode binaries.  */
+extern bool mips_accept_ieee754_relaxed;
+
 extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
 			    bool is_interp, struct arch_elf_state *state);
 
Index: linux-sfr-test/arch/mips/include/asm/thread_info.h
===================================================================
--- linux-sfr-test.orig/arch/mips/include/asm/thread_info.h	2015-11-11 02:21:08.160573000 +0000
+++ linux-sfr-test/arch/mips/include/asm/thread_info.h	2015-11-11 12:22:51.855825000 +0000
@@ -102,6 +102,7 @@ static inline struct thread_info *curren
 #define TIF_UPROBE		6	/* breakpointed or singlestepping */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
+#define TIF_IEEE754_RELAXED	17	/* Relaxed IEEE Std 754 rules */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_NOHZ		19	/* in adaptive nohz mode */
 #define TIF_FIXADE		20	/* Fix address errors in software */
Index: linux-sfr-test/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/cpu-probe.c	2015-11-11 02:21:08.161578000 +0000
+++ linux-sfr-test/arch/mips/kernel/cpu-probe.c	2015-11-11 12:22:51.859824000 +0000
@@ -154,13 +154,15 @@ static void cpu_set_fpu_2008(struct cpui
  * IEEE 754 conformance mode to use.  Affects the NaN encoding and the
  * ABS.fmt/NEG.fmt execution mode.
  */
-static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT;
+static enum {
+	STRICTEST, STRICT, BEST, LEGACY, STD2008, RELAXED
+} ieee754 = STRICT;
 
 /*
  * Set the IEEE 754 NaN encodings and the ABS.fmt/NEG.fmt execution modes
  * to support by the FPU emulator according to the IEEE 754 conformance
- * mode selected.  Note that "relaxed" straps the emulator so that it
- * allows 2008-NaN binaries even for legacy processors.
+ * mode selected.  Note that "best" and "relaxed" strap the emulator so
+ * that it allows 2008-NaN binaries even for legacy processors.
  */
 static void cpu_set_nofpu_2008(struct cpuinfo_mips *c)
 {
@@ -169,6 +171,7 @@ static void cpu_set_nofpu_2008(struct cp
 	c->fpu_msk31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
 
 	switch (ieee754) {
+	case STRICTEST:
 	case STRICT:
 		if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
 				    MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
@@ -179,6 +182,9 @@ static void cpu_set_nofpu_2008(struct cp
 			c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
 		}
 		break;
+	case BEST:
+		c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY;
+		break;
 	case LEGACY:
 		c->options |= MIPS_CPU_NAN_LEGACY;
 		c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
@@ -200,8 +206,13 @@ static void cpu_set_nofpu_2008(struct cp
  */
 static void cpu_set_nan_2008(struct cpuinfo_mips *c)
 {
+	mips_default_ieee754_relaxed = ieee754 == RELAXED;
+	mips_accept_ieee754_relaxed = ieee754 != STRICTEST;
+
 	switch (ieee754) {
+	case STRICTEST:
 	case STRICT:
+	case BEST:
 		mips_use_nan_legacy = !!cpu_has_nan_legacy;
 		mips_use_nan_2008 = !!cpu_has_nan_2008;
 		break;
@@ -224,17 +235,23 @@ static void cpu_set_nan_2008(struct cpui
  * IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode override
  * settings:
  *
- * strict:  accept binaries that request a NaN encoding supported by the FPU
- * legacy:  only accept legacy-NaN binaries
- * 2008:    only accept 2008-NaN binaries
- * relaxed: accept any binaries regardless of whether supported by the FPU
+ * strictest: require binaries to request a NaN encoding supported by the FPU
+ * strict:    accept binaries that request a NaN encoding supported by the FPU
+ * best:      accept all binaries in full FP emulation, otherwise like "strict"
+ * legacy:    only accept legacy-NaN binaries
+ * 2008:      only accept 2008-NaN binaries
+ * relaxed:   accept any binaries regardless of whether supported by the FPU
  */
 static int __init ieee754_setup(char *s)
 {
 	if (!s)
 		return -1;
+	else if (!strcmp(s, "strictest"))
+		ieee754 = STRICTEST;
 	else if (!strcmp(s, "strict"))
 		ieee754 = STRICT;
+	else if (!strcmp(s, "best"))
+		ieee754 = BEST;
 	else if (!strcmp(s, "legacy"))
 		ieee754 = LEGACY;
 	else if (!strcmp(s, "2008"))
Index: linux-sfr-test/arch/mips/kernel/elf.c
===================================================================
--- linux-sfr-test.orig/arch/mips/kernel/elf.c	2015-11-11 02:21:08.163575000 +0000
+++ linux-sfr-test/arch/mips/kernel/elf.c	2015-11-11 12:22:51.861832000 +0000
@@ -17,6 +17,12 @@
 bool mips_use_nan_legacy;
 bool mips_use_nan_2008;
 
+/* Whether to select the IEEE Std 754 relaxed compliance mode by default.  */
+bool mips_default_ieee754_relaxed;
+
+/* Whether to accept IEEE Std 754 relaxed compliance mode binaries.  */
+bool mips_accept_ieee754_relaxed;
+
 /* FPU modes */
 enum {
 	FP_FRE,
@@ -81,6 +87,7 @@ int arch_elf_pt_proc(void *_ehdr, void *
 	struct elf32_phdr *phdr32 = _phdr;
 	struct elf64_phdr *phdr64 = _phdr;
 	struct mips_elf_abiflags_v0 abiflags;
+	bool relaxed;
 	bool elf32;
 	u32 flags;
 	int ret;
@@ -131,6 +138,17 @@ int arch_elf_pt_proc(void *_ehdr, void *
 	else
 		state->fp_abi = abiflags.fp_abi;
 
+	/* Record any requested IEEE Std 754 compliance mode.  */
+	relaxed = !!(abiflags.flags2 & MIPS_AFL_FLAGS2_RELAXED);
+	if (abiflags.flags1 & MIPS_AFL_FLAGS1_IEEE) {
+		if (is_interp)
+			state->interp_ieee754_relaxed = relaxed;
+		else
+			state->ieee754_relaxed = relaxed;
+	} else if (relaxed) {
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -147,6 +165,7 @@ int arch_check_elf(void *_ehdr, bool has
 	} *iehdr = _interp_ehdr;
 	struct mode_req prog_req, interp_req;
 	int fp_abi, interp_fp_abi, abi0, abi1, max_abi;
+	bool relaxed;
 	bool elf32;
 	u32 flags;
 
@@ -155,23 +174,31 @@ int arch_check_elf(void *_ehdr, bool has
 
 	/*
 	 * Determine the NaN personality, reject the binary if not allowed.
-	 * Also ensure that any interpreter matches the executable.
+	 * Check hardware support if strict conformance requested by the
+	 * binary, otherwise respect any kernel override.  Also ensure that
+	 * any interpreter matches the executable.
 	 */
+	relaxed = state->ieee754_relaxed;
+	if (relaxed && !mips_accept_ieee754_relaxed)
+		return -ENOEXEC;
 	if (flags & EF_MIPS_NAN2008) {
-		if (mips_use_nan_2008)
-			state->nan_2008 = 1;
+		if (relaxed || mips_use_nan_2008)
+			state->nan_2008 = mips_use_nan_2008;
 		else
 			return -ENOEXEC;
 	} else {
-		if (mips_use_nan_legacy)
-			state->nan_2008 = 0;
+		if (relaxed || mips_use_nan_legacy)
+			state->nan_2008 = !mips_use_nan_legacy;
 		else
 			return -ENOEXEC;
 	}
-	if (has_interpreter) {
+	if (has_interpreter && !relaxed) {
 		bool ielf32;
 		u32 iflags;
 
+		if (state->interp_ieee754_relaxed)
+			return -ELIBBAD;
+
 		ielf32 = iehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
 		iflags = ielf32 ? iehdr->e32.e_flags : iehdr->e64.e_flags;
 
@@ -312,6 +339,11 @@ void mips_set_personality_nan(struct arc
 	struct cpuinfo_mips *c = &boot_cpu_data;
 	struct task_struct *t = current;
 
+	if (state->ieee754_relaxed)
+		set_thread_flag(TIF_IEEE754_RELAXED);
+	else
+		clear_thread_flag(TIF_IEEE754_RELAXED);
+
 	t->thread.fpu.fcr31 = c->fpu_csr31;
 	switch (state->nan_2008) {
 	case 0:
Index: linux-sfr-test/arch/mips/math-emu/ieee754dp.c
===================================================================
--- linux-sfr-test.orig/arch/mips/math-emu/ieee754dp.c	2015-11-11 02:21:08.165573000 +0000
+++ linux-sfr-test/arch/mips/math-emu/ieee754dp.c	2015-11-11 12:22:51.884826000 +0000
@@ -53,7 +53,8 @@ union ieee754dp __cold ieee754dp_nanxcpt
 {
 	assert(ieee754dp_issnan(r));
 
-	ieee754_setcx(IEEE754_INVALID_OPERATION);
+	if (!test_thread_flag(TIF_IEEE754_RELAXED))
+		ieee754_setcx(IEEE754_INVALID_OPERATION);
 	if (ieee754_csr.nan2008) {
 		DPMANT(r) |= DP_MBIT(DP_FBITS - 1);
 	} else {
Index: linux-sfr-test/arch/mips/math-emu/ieee754sp.c
===================================================================
--- linux-sfr-test.orig/arch/mips/math-emu/ieee754sp.c	2015-11-11 02:21:08.167574000 +0000
+++ linux-sfr-test/arch/mips/math-emu/ieee754sp.c	2015-11-11 12:22:51.887824000 +0000
@@ -53,7 +53,8 @@ union ieee754sp __cold ieee754sp_nanxcpt
 {
 	assert(ieee754sp_issnan(r));
 
-	ieee754_setcx(IEEE754_INVALID_OPERATION);
+	if (!test_thread_flag(TIF_IEEE754_RELAXED))
+		ieee754_setcx(IEEE754_INVALID_OPERATION);
 	if (ieee754_csr.nan2008) {
 		SPMANT(r) |= SP_MBIT(SP_FBITS - 1);
 	} else {

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 4/4] prctl: Add MIPS IEEE Std 754 compliance mode switching
@ 2015-11-16 14:35   ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:35 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

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@imgtec.com>
---
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;

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFC PATCH 4/4] prctl: Add MIPS IEEE Std 754 compliance mode switching
@ 2015-11-16 14:35   ` Maciej W. Rozycki
  0 siblings, 0 replies; 10+ messages in thread
From: Maciej W. Rozycki @ 2015-11-16 14:35 UTC (permalink / raw)
  To: linux-mips
  Cc: Ralf Baechle, Matthew Fortune, Daniel Sanders, Leonid Yegoshin,
	linux-kernel

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@imgtec.com>
---
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;

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-11-16 14:35 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-16 14:34 [RFC PATCH 0/4] MIPS: IEEE Std 754 NaN interlinking support Maciej W. Rozycki
2015-11-16 14:34 ` Maciej W. Rozycki
2015-11-16 14:34 ` [RFC PATCH 1/4] ELF: Add platform-specific AT_FLAGS initialisation support Maciej W. Rozycki
2015-11-16 14:34   ` Maciej W. Rozycki
2015-11-16 14:34 ` [RFC PATCH 2/4] MIPS: Factor out FP context preemption Maciej W. Rozycki
2015-11-16 14:34   ` Maciej W. Rozycki
2015-11-16 14:35 ` [RFC PATCH 3/4] MIPS: Implement IEEE Std 754 NaN interlinking support Maciej W. Rozycki
2015-11-16 14:35   ` Maciej W. Rozycki
2015-11-16 14:35 ` [RFC PATCH 4/4] prctl: Add MIPS IEEE Std 754 compliance mode switching Maciej W. Rozycki
2015-11-16 14:35   ` Maciej W. Rozycki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.