All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] MIPS ptrace/core dump fixes and cleanups
@ 2014-07-23 13:40 Alex Smith
  2014-07-23 13:40   ` Alex Smith
                   ` (10 more replies)
  0 siblings, 11 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith

Hi,

This patch set includes a number of fixes and cleanups for ptrace and
core dumps. The bulk of the changes are to make core dumps work again,
which have been broken since the core dumper was switched to use
regsets.

This series applies on top of Ralf's mips-for-linux-next branch.

Thanks,
Alex

Alex Smith (11):
  MIPS: ptrace: Avoid smp_processor_id() when retrieving FPU IR
  MIPS: ptrace: Test correct task's flags in task_user_regset_view()
  MIPS: asm/reg.h: Make 32- and 64-bit definitions available at the same
    time
  MIPS: ptrace: Change GP regset to use correct core dump register
    layout
  MIPS: ptrace: Always copy FCSR in FP regset
  MIPS: O32/32-bit: Fix bug which can cause incorrect system call
    restarts
  MIPS: O32/32-bit: Remove outdated comment
  MIPS: ptrace: Fix user pt_regs definition, use in
    ptrace_{get,set}regs()
  MIPS: Remove old core dump functions
  MIPS: Remove asm/user.h
  MIPS: asm/reg.h: Move to uapi

 arch/mips/include/asm/Kbuild        |   1 +
 arch/mips/include/asm/elf.h         |  17 ---
 arch/mips/include/asm/ptrace.h      |   8 +-
 arch/mips/include/asm/reg.h         | 129 +----------------
 arch/mips/include/asm/user.h        |  58 --------
 arch/mips/include/uapi/asm/ptrace.h |  25 ++--
 arch/mips/include/uapi/asm/reg.h    | 206 ++++++++++++++++++++++++++
 arch/mips/kernel/binfmt_elfo32.c    |  38 -----
 arch/mips/kernel/process.c          |  57 +-------
 arch/mips/kernel/ptrace.c           | 281 +++++++++++++++++++++++++++---------
 arch/mips/kernel/ptrace32.c         |  10 +-
 arch/mips/kernel/scall32-o32.S      |   2 -
 12 files changed, 447 insertions(+), 385 deletions(-)
 delete mode 100644 arch/mips/include/asm/user.h
 create mode 100644 arch/mips/include/uapi/asm/reg.h

-- 
1.9.1

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

* [PATCH 01/11] MIPS: ptrace: Avoid smp_processor_id() when retrieving FPU IR
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

Whenever ptrace attempts to retrieve the FPU implementation register it
accesses it through current_cpu_data, which calls smp_processor_id().
Since the code may execute with preemption enabled, this can trigger
a warning. Fix this by using boot_cpu_data to get the IR instead.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: <stable@vger.kernel.org> # v3.15+
---
 arch/mips/kernel/ptrace.c   | 4 ++--
 arch/mips/kernel/ptrace32.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f639ccd..6063b11 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -129,7 +129,7 @@ int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
 	}
 
 	__put_user(child->thread.fpu.fcr31, data + 64);
-	__put_user(current_cpu_data.fpu_id, data + 65);
+	__put_user(boot_cpu_data.fpu_id, data + 65);
 
 	return 0;
 }
@@ -480,7 +480,7 @@ long arch_ptrace(struct task_struct *child, long request,
 			break;
 		case FPC_EIR:
 			/* implementation / version register */
-			tmp = current_cpu_data.fpu_id;
+			tmp = boot_cpu_data.fpu_id;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index b40c3ca..a83fb73 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -129,7 +129,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 			break;
 		case FPC_EIR:
 			/* implementation / version register */
-			tmp = current_cpu_data.fpu_id;
+			tmp = boot_cpu_data.fpu_id;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
-- 
1.9.1

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

* [PATCH 01/11] MIPS: ptrace: Avoid smp_processor_id() when retrieving FPU IR
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

Whenever ptrace attempts to retrieve the FPU implementation register it
accesses it through current_cpu_data, which calls smp_processor_id().
Since the code may execute with preemption enabled, this can trigger
a warning. Fix this by using boot_cpu_data to get the IR instead.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: <stable@vger.kernel.org> # v3.15+
---
 arch/mips/kernel/ptrace.c   | 4 ++--
 arch/mips/kernel/ptrace32.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index f639ccd..6063b11 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -129,7 +129,7 @@ int ptrace_getfpregs(struct task_struct *child, __u32 __user *data)
 	}
 
 	__put_user(child->thread.fpu.fcr31, data + 64);
-	__put_user(current_cpu_data.fpu_id, data + 65);
+	__put_user(boot_cpu_data.fpu_id, data + 65);
 
 	return 0;
 }
@@ -480,7 +480,7 @@ long arch_ptrace(struct task_struct *child, long request,
 			break;
 		case FPC_EIR:
 			/* implementation / version register */
-			tmp = current_cpu_data.fpu_id;
+			tmp = boot_cpu_data.fpu_id;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index b40c3ca..a83fb73 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -129,7 +129,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 			break;
 		case FPC_EIR:
 			/* implementation / version register */
-			tmp = current_cpu_data.fpu_id;
+			tmp = boot_cpu_data.fpu_id;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
-- 
1.9.1

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

* [PATCH 02/11] MIPS: ptrace: Test correct task's flags in task_user_regset_view()
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

task_user_regset_view() should test for TIF_32BIT_REGS in the flags of
the specified task, not of the current task.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: <stable@vger.kernel.org> # v3.13+
---
 arch/mips/kernel/ptrace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 6063b11..8f2130a 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -398,7 +398,7 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 #endif
 
 #ifdef CONFIG_MIPS32_O32
-		if (test_thread_flag(TIF_32BIT_REGS))
+		if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
 			return &user_mips_view;
 #endif
 
-- 
1.9.1

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

* [PATCH 02/11] MIPS: ptrace: Test correct task's flags in task_user_regset_view()
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

task_user_regset_view() should test for TIF_32BIT_REGS in the flags of
the specified task, not of the current task.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: <stable@vger.kernel.org> # v3.13+
---
 arch/mips/kernel/ptrace.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 6063b11..8f2130a 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -398,7 +398,7 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 #endif
 
 #ifdef CONFIG_MIPS32_O32
-		if (test_thread_flag(TIF_32BIT_REGS))
+		if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
 			return &user_mips_view;
 #endif
 
-- 
1.9.1

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

* [PATCH 03/11] MIPS: asm/reg.h: Make 32- and 64-bit definitions available at the same time
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

Get rid of the WANT_COMPAT_REG_H test and instead define both the 32-
and 64-bit register offset definitions at the same time with
MIPS{32,64}_ prefixes, then define the existing EF_* names to the
correct definitions for the kernel's bitness.

This patch is a prerequisite of the following bug fix patch.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: <stable@vger.kernel.org> # v3.13+
---
 arch/mips/include/asm/reg.h      | 260 +++++++++++++++++++++++++--------------
 arch/mips/kernel/binfmt_elfo32.c |  32 ++---
 2 files changed, 182 insertions(+), 110 deletions(-)

diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h
index 910e71a..b8343cc 100644
--- a/arch/mips/include/asm/reg.h
+++ b/arch/mips/include/asm/reg.h
@@ -12,116 +12,194 @@
 #ifndef __ASM_MIPS_REG_H
 #define __ASM_MIPS_REG_H
 
-
-#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H)
-
-#define EF_R0			6
-#define EF_R1			7
-#define EF_R2			8
-#define EF_R3			9
-#define EF_R4			10
-#define EF_R5			11
-#define EF_R6			12
-#define EF_R7			13
-#define EF_R8			14
-#define EF_R9			15
-#define EF_R10			16
-#define EF_R11			17
-#define EF_R12			18
-#define EF_R13			19
-#define EF_R14			20
-#define EF_R15			21
-#define EF_R16			22
-#define EF_R17			23
-#define EF_R18			24
-#define EF_R19			25
-#define EF_R20			26
-#define EF_R21			27
-#define EF_R22			28
-#define EF_R23			29
-#define EF_R24			30
-#define EF_R25			31
+#define MIPS32_EF_R0		6
+#define MIPS32_EF_R1		7
+#define MIPS32_EF_R2		8
+#define MIPS32_EF_R3		9
+#define MIPS32_EF_R4		10
+#define MIPS32_EF_R5		11
+#define MIPS32_EF_R6		12
+#define MIPS32_EF_R7		13
+#define MIPS32_EF_R8		14
+#define MIPS32_EF_R9		15
+#define MIPS32_EF_R10		16
+#define MIPS32_EF_R11		17
+#define MIPS32_EF_R12		18
+#define MIPS32_EF_R13		19
+#define MIPS32_EF_R14		20
+#define MIPS32_EF_R15		21
+#define MIPS32_EF_R16		22
+#define MIPS32_EF_R17		23
+#define MIPS32_EF_R18		24
+#define MIPS32_EF_R19		25
+#define MIPS32_EF_R20		26
+#define MIPS32_EF_R21		27
+#define MIPS32_EF_R22		28
+#define MIPS32_EF_R23		29
+#define MIPS32_EF_R24		30
+#define MIPS32_EF_R25		31
 
 /*
  * k0/k1 unsaved
  */
-#define EF_R26			32
-#define EF_R27			33
+#define MIPS32_EF_R26		32
+#define MIPS32_EF_R27		33
 
-#define EF_R28			34
-#define EF_R29			35
-#define EF_R30			36
-#define EF_R31			37
+#define MIPS32_EF_R28		34
+#define MIPS32_EF_R29		35
+#define MIPS32_EF_R30		36
+#define MIPS32_EF_R31		37
 
 /*
  * Saved special registers
  */
-#define EF_LO			38
-#define EF_HI			39
-
-#define EF_CP0_EPC		40
-#define EF_CP0_BADVADDR		41
-#define EF_CP0_STATUS		42
-#define EF_CP0_CAUSE		43
-#define EF_UNUSED0		44
-
-#define EF_SIZE			180
-
-#endif
-
-#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H)
-
-#define EF_R0			 0
-#define EF_R1			 1
-#define EF_R2			 2
-#define EF_R3			 3
-#define EF_R4			 4
-#define EF_R5			 5
-#define EF_R6			 6
-#define EF_R7			 7
-#define EF_R8			 8
-#define EF_R9			 9
-#define EF_R10			10
-#define EF_R11			11
-#define EF_R12			12
-#define EF_R13			13
-#define EF_R14			14
-#define EF_R15			15
-#define EF_R16			16
-#define EF_R17			17
-#define EF_R18			18
-#define EF_R19			19
-#define EF_R20			20
-#define EF_R21			21
-#define EF_R22			22
-#define EF_R23			23
-#define EF_R24			24
-#define EF_R25			25
+#define MIPS32_EF_LO		38
+#define MIPS32_EF_HI		39
+
+#define MIPS32_EF_CP0_EPC	40
+#define MIPS32_EF_CP0_BADVADDR	41
+#define MIPS32_EF_CP0_STATUS	42
+#define MIPS32_EF_CP0_CAUSE	43
+#define MIPS32_EF_UNUSED0	44
+
+#define MIPS32_EF_SIZE		180
+
+#define MIPS64_EF_R0		0
+#define MIPS64_EF_R1		1
+#define MIPS64_EF_R2		2
+#define MIPS64_EF_R3		3
+#define MIPS64_EF_R4		4
+#define MIPS64_EF_R5		5
+#define MIPS64_EF_R6		6
+#define MIPS64_EF_R7		7
+#define MIPS64_EF_R8		8
+#define MIPS64_EF_R9		9
+#define MIPS64_EF_R10		10
+#define MIPS64_EF_R11		11
+#define MIPS64_EF_R12		12
+#define MIPS64_EF_R13		13
+#define MIPS64_EF_R14		14
+#define MIPS64_EF_R15		15
+#define MIPS64_EF_R16		16
+#define MIPS64_EF_R17		17
+#define MIPS64_EF_R18		18
+#define MIPS64_EF_R19		19
+#define MIPS64_EF_R20		20
+#define MIPS64_EF_R21		21
+#define MIPS64_EF_R22		22
+#define MIPS64_EF_R23		23
+#define MIPS64_EF_R24		24
+#define MIPS64_EF_R25		25
 
 /*
  * k0/k1 unsaved
  */
-#define EF_R26			26
-#define EF_R27			27
+#define MIPS64_EF_R26		26
+#define MIPS64_EF_R27		27
 
 
-#define EF_R28			28
-#define EF_R29			29
-#define EF_R30			30
-#define EF_R31			31
+#define MIPS64_EF_R28		28
+#define MIPS64_EF_R29		29
+#define MIPS64_EF_R30		30
+#define MIPS64_EF_R31		31
 
 /*
  * Saved special registers
  */
-#define EF_LO			32
-#define EF_HI			33
-
-#define EF_CP0_EPC		34
-#define EF_CP0_BADVADDR		35
-#define EF_CP0_STATUS		36
-#define EF_CP0_CAUSE		37
-
-#define EF_SIZE			304	/* size in bytes */
+#define MIPS64_EF_LO		32
+#define MIPS64_EF_HI		33
+
+#define MIPS64_EF_CP0_EPC	34
+#define MIPS64_EF_CP0_BADVADDR	35
+#define MIPS64_EF_CP0_STATUS	36
+#define MIPS64_EF_CP0_CAUSE	37
+
+#define MIPS64_EF_SIZE		304	/* size in bytes */
+
+#if defined(CONFIG_32BIT)
+
+#define EF_R0			MIPS32_EF_R0
+#define EF_R1			MIPS32_EF_R1
+#define EF_R2			MIPS32_EF_R2
+#define EF_R3			MIPS32_EF_R3
+#define EF_R4			MIPS32_EF_R4
+#define EF_R5			MIPS32_EF_R5
+#define EF_R6			MIPS32_EF_R6
+#define EF_R7			MIPS32_EF_R7
+#define EF_R8			MIPS32_EF_R8
+#define EF_R9			MIPS32_EF_R9
+#define EF_R10			MIPS32_EF_R10
+#define EF_R11			MIPS32_EF_R11
+#define EF_R12			MIPS32_EF_R12
+#define EF_R13			MIPS32_EF_R13
+#define EF_R14			MIPS32_EF_R14
+#define EF_R15			MIPS32_EF_R15
+#define EF_R16			MIPS32_EF_R16
+#define EF_R17			MIPS32_EF_R17
+#define EF_R18			MIPS32_EF_R18
+#define EF_R19			MIPS32_EF_R19
+#define EF_R20			MIPS32_EF_R20
+#define EF_R21			MIPS32_EF_R21
+#define EF_R22			MIPS32_EF_R22
+#define EF_R23			MIPS32_EF_R23
+#define EF_R24			MIPS32_EF_R24
+#define EF_R25			MIPS32_EF_R25
+#define EF_R26			MIPS32_EF_R26
+#define EF_R27			MIPS32_EF_R27
+#define EF_R28			MIPS32_EF_R28
+#define EF_R29			MIPS32_EF_R29
+#define EF_R30			MIPS32_EF_R30
+#define EF_R31			MIPS32_EF_R31
+#define EF_LO			MIPS32_EF_LO
+#define EF_HI			MIPS32_EF_HI
+#define EF_CP0_EPC		MIPS32_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS32_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS32_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS32_EF_CP0_CAUSE
+#define EF_UNUSED0		MIPS32_EF_UNUSED0
+#define EF_SIZE			MIPS32_EF_SIZE
+
+#elif defined(CONFIG_64BIT)
+
+#define EF_R0			MIPS64_EF_R0
+#define EF_R1			MIPS64_EF_R1
+#define EF_R2			MIPS64_EF_R2
+#define EF_R3			MIPS64_EF_R3
+#define EF_R4			MIPS64_EF_R4
+#define EF_R5			MIPS64_EF_R5
+#define EF_R6			MIPS64_EF_R6
+#define EF_R7			MIPS64_EF_R7
+#define EF_R8			MIPS64_EF_R8
+#define EF_R9			MIPS64_EF_R9
+#define EF_R10			MIPS64_EF_R10
+#define EF_R11			MIPS64_EF_R11
+#define EF_R12			MIPS64_EF_R12
+#define EF_R13			MIPS64_EF_R13
+#define EF_R14			MIPS64_EF_R14
+#define EF_R15			MIPS64_EF_R15
+#define EF_R16			MIPS64_EF_R16
+#define EF_R17			MIPS64_EF_R17
+#define EF_R18			MIPS64_EF_R18
+#define EF_R19			MIPS64_EF_R19
+#define EF_R20			MIPS64_EF_R20
+#define EF_R21			MIPS64_EF_R21
+#define EF_R22			MIPS64_EF_R22
+#define EF_R23			MIPS64_EF_R23
+#define EF_R24			MIPS64_EF_R24
+#define EF_R25			MIPS64_EF_R25
+#define EF_R26			MIPS64_EF_R26
+#define EF_R27			MIPS64_EF_R27
+#define EF_R28			MIPS64_EF_R28
+#define EF_R29			MIPS64_EF_R29
+#define EF_R30			MIPS64_EF_R30
+#define EF_R31			MIPS64_EF_R31
+#define EF_LO			MIPS64_EF_LO
+#define EF_HI			MIPS64_EF_HI
+#define EF_CP0_EPC		MIPS64_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS64_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS64_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS64_EF_CP0_CAUSE
+#define EF_SIZE			MIPS64_EF_SIZE
 
 #endif /* CONFIG_64BIT */
 
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 7faf5f2..71df942 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -72,12 +72,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 #include <asm/processor.h>
 
-/*
- * When this file is selected, we are definitely running a 64bit kernel.
- * So using the right regs define in asm/reg.h
- */
-#define WANT_COMPAT_REG_H
-
 /* These MUST be defined before elf.h gets included */
 extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs);
 #define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
@@ -149,21 +143,21 @@ void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
 {
 	int i;
 
-	for (i = 0; i < EF_R0; i++)
+	for (i = 0; i < MIPS32_EF_R0; i++)
 		grp[i] = 0;
-	grp[EF_R0] = 0;
+	grp[MIPS32_EF_R0] = 0;
 	for (i = 1; i <= 31; i++)
-		grp[EF_R0 + i] = (elf_greg_t) regs->regs[i];
-	grp[EF_R26] = 0;
-	grp[EF_R27] = 0;
-	grp[EF_LO] = (elf_greg_t) regs->lo;
-	grp[EF_HI] = (elf_greg_t) regs->hi;
-	grp[EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
-	grp[EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
-	grp[EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
-	grp[EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
-#ifdef EF_UNUSED0
-	grp[EF_UNUSED0] = 0;
+		grp[MIPS32_EF_R0 + i] = (elf_greg_t) regs->regs[i];
+	grp[MIPS32_EF_R26] = 0;
+	grp[MIPS32_EF_R27] = 0;
+	grp[MIPS32_EF_LO] = (elf_greg_t) regs->lo;
+	grp[MIPS32_EF_HI] = (elf_greg_t) regs->hi;
+	grp[MIPS32_EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
+	grp[MIPS32_EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
+	grp[MIPS32_EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
+	grp[MIPS32_EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
+#ifdef MIPS32_EF_UNUSED0
+	grp[MIPS32_EF_UNUSED0] = 0;
 #endif
 }
 
-- 
1.9.1

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

* [PATCH 03/11] MIPS: asm/reg.h: Make 32- and 64-bit definitions available at the same time
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

Get rid of the WANT_COMPAT_REG_H test and instead define both the 32-
and 64-bit register offset definitions at the same time with
MIPS{32,64}_ prefixes, then define the existing EF_* names to the
correct definitions for the kernel's bitness.

This patch is a prerequisite of the following bug fix patch.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: <stable@vger.kernel.org> # v3.13+
---
 arch/mips/include/asm/reg.h      | 260 +++++++++++++++++++++++++--------------
 arch/mips/kernel/binfmt_elfo32.c |  32 ++---
 2 files changed, 182 insertions(+), 110 deletions(-)

diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h
index 910e71a..b8343cc 100644
--- a/arch/mips/include/asm/reg.h
+++ b/arch/mips/include/asm/reg.h
@@ -12,116 +12,194 @@
 #ifndef __ASM_MIPS_REG_H
 #define __ASM_MIPS_REG_H
 
-
-#if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H)
-
-#define EF_R0			6
-#define EF_R1			7
-#define EF_R2			8
-#define EF_R3			9
-#define EF_R4			10
-#define EF_R5			11
-#define EF_R6			12
-#define EF_R7			13
-#define EF_R8			14
-#define EF_R9			15
-#define EF_R10			16
-#define EF_R11			17
-#define EF_R12			18
-#define EF_R13			19
-#define EF_R14			20
-#define EF_R15			21
-#define EF_R16			22
-#define EF_R17			23
-#define EF_R18			24
-#define EF_R19			25
-#define EF_R20			26
-#define EF_R21			27
-#define EF_R22			28
-#define EF_R23			29
-#define EF_R24			30
-#define EF_R25			31
+#define MIPS32_EF_R0		6
+#define MIPS32_EF_R1		7
+#define MIPS32_EF_R2		8
+#define MIPS32_EF_R3		9
+#define MIPS32_EF_R4		10
+#define MIPS32_EF_R5		11
+#define MIPS32_EF_R6		12
+#define MIPS32_EF_R7		13
+#define MIPS32_EF_R8		14
+#define MIPS32_EF_R9		15
+#define MIPS32_EF_R10		16
+#define MIPS32_EF_R11		17
+#define MIPS32_EF_R12		18
+#define MIPS32_EF_R13		19
+#define MIPS32_EF_R14		20
+#define MIPS32_EF_R15		21
+#define MIPS32_EF_R16		22
+#define MIPS32_EF_R17		23
+#define MIPS32_EF_R18		24
+#define MIPS32_EF_R19		25
+#define MIPS32_EF_R20		26
+#define MIPS32_EF_R21		27
+#define MIPS32_EF_R22		28
+#define MIPS32_EF_R23		29
+#define MIPS32_EF_R24		30
+#define MIPS32_EF_R25		31
 
 /*
  * k0/k1 unsaved
  */
-#define EF_R26			32
-#define EF_R27			33
+#define MIPS32_EF_R26		32
+#define MIPS32_EF_R27		33
 
-#define EF_R28			34
-#define EF_R29			35
-#define EF_R30			36
-#define EF_R31			37
+#define MIPS32_EF_R28		34
+#define MIPS32_EF_R29		35
+#define MIPS32_EF_R30		36
+#define MIPS32_EF_R31		37
 
 /*
  * Saved special registers
  */
-#define EF_LO			38
-#define EF_HI			39
-
-#define EF_CP0_EPC		40
-#define EF_CP0_BADVADDR		41
-#define EF_CP0_STATUS		42
-#define EF_CP0_CAUSE		43
-#define EF_UNUSED0		44
-
-#define EF_SIZE			180
-
-#endif
-
-#if defined(CONFIG_64BIT) && !defined(WANT_COMPAT_REG_H)
-
-#define EF_R0			 0
-#define EF_R1			 1
-#define EF_R2			 2
-#define EF_R3			 3
-#define EF_R4			 4
-#define EF_R5			 5
-#define EF_R6			 6
-#define EF_R7			 7
-#define EF_R8			 8
-#define EF_R9			 9
-#define EF_R10			10
-#define EF_R11			11
-#define EF_R12			12
-#define EF_R13			13
-#define EF_R14			14
-#define EF_R15			15
-#define EF_R16			16
-#define EF_R17			17
-#define EF_R18			18
-#define EF_R19			19
-#define EF_R20			20
-#define EF_R21			21
-#define EF_R22			22
-#define EF_R23			23
-#define EF_R24			24
-#define EF_R25			25
+#define MIPS32_EF_LO		38
+#define MIPS32_EF_HI		39
+
+#define MIPS32_EF_CP0_EPC	40
+#define MIPS32_EF_CP0_BADVADDR	41
+#define MIPS32_EF_CP0_STATUS	42
+#define MIPS32_EF_CP0_CAUSE	43
+#define MIPS32_EF_UNUSED0	44
+
+#define MIPS32_EF_SIZE		180
+
+#define MIPS64_EF_R0		0
+#define MIPS64_EF_R1		1
+#define MIPS64_EF_R2		2
+#define MIPS64_EF_R3		3
+#define MIPS64_EF_R4		4
+#define MIPS64_EF_R5		5
+#define MIPS64_EF_R6		6
+#define MIPS64_EF_R7		7
+#define MIPS64_EF_R8		8
+#define MIPS64_EF_R9		9
+#define MIPS64_EF_R10		10
+#define MIPS64_EF_R11		11
+#define MIPS64_EF_R12		12
+#define MIPS64_EF_R13		13
+#define MIPS64_EF_R14		14
+#define MIPS64_EF_R15		15
+#define MIPS64_EF_R16		16
+#define MIPS64_EF_R17		17
+#define MIPS64_EF_R18		18
+#define MIPS64_EF_R19		19
+#define MIPS64_EF_R20		20
+#define MIPS64_EF_R21		21
+#define MIPS64_EF_R22		22
+#define MIPS64_EF_R23		23
+#define MIPS64_EF_R24		24
+#define MIPS64_EF_R25		25
 
 /*
  * k0/k1 unsaved
  */
-#define EF_R26			26
-#define EF_R27			27
+#define MIPS64_EF_R26		26
+#define MIPS64_EF_R27		27
 
 
-#define EF_R28			28
-#define EF_R29			29
-#define EF_R30			30
-#define EF_R31			31
+#define MIPS64_EF_R28		28
+#define MIPS64_EF_R29		29
+#define MIPS64_EF_R30		30
+#define MIPS64_EF_R31		31
 
 /*
  * Saved special registers
  */
-#define EF_LO			32
-#define EF_HI			33
-
-#define EF_CP0_EPC		34
-#define EF_CP0_BADVADDR		35
-#define EF_CP0_STATUS		36
-#define EF_CP0_CAUSE		37
-
-#define EF_SIZE			304	/* size in bytes */
+#define MIPS64_EF_LO		32
+#define MIPS64_EF_HI		33
+
+#define MIPS64_EF_CP0_EPC	34
+#define MIPS64_EF_CP0_BADVADDR	35
+#define MIPS64_EF_CP0_STATUS	36
+#define MIPS64_EF_CP0_CAUSE	37
+
+#define MIPS64_EF_SIZE		304	/* size in bytes */
+
+#if defined(CONFIG_32BIT)
+
+#define EF_R0			MIPS32_EF_R0
+#define EF_R1			MIPS32_EF_R1
+#define EF_R2			MIPS32_EF_R2
+#define EF_R3			MIPS32_EF_R3
+#define EF_R4			MIPS32_EF_R4
+#define EF_R5			MIPS32_EF_R5
+#define EF_R6			MIPS32_EF_R6
+#define EF_R7			MIPS32_EF_R7
+#define EF_R8			MIPS32_EF_R8
+#define EF_R9			MIPS32_EF_R9
+#define EF_R10			MIPS32_EF_R10
+#define EF_R11			MIPS32_EF_R11
+#define EF_R12			MIPS32_EF_R12
+#define EF_R13			MIPS32_EF_R13
+#define EF_R14			MIPS32_EF_R14
+#define EF_R15			MIPS32_EF_R15
+#define EF_R16			MIPS32_EF_R16
+#define EF_R17			MIPS32_EF_R17
+#define EF_R18			MIPS32_EF_R18
+#define EF_R19			MIPS32_EF_R19
+#define EF_R20			MIPS32_EF_R20
+#define EF_R21			MIPS32_EF_R21
+#define EF_R22			MIPS32_EF_R22
+#define EF_R23			MIPS32_EF_R23
+#define EF_R24			MIPS32_EF_R24
+#define EF_R25			MIPS32_EF_R25
+#define EF_R26			MIPS32_EF_R26
+#define EF_R27			MIPS32_EF_R27
+#define EF_R28			MIPS32_EF_R28
+#define EF_R29			MIPS32_EF_R29
+#define EF_R30			MIPS32_EF_R30
+#define EF_R31			MIPS32_EF_R31
+#define EF_LO			MIPS32_EF_LO
+#define EF_HI			MIPS32_EF_HI
+#define EF_CP0_EPC		MIPS32_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS32_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS32_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS32_EF_CP0_CAUSE
+#define EF_UNUSED0		MIPS32_EF_UNUSED0
+#define EF_SIZE			MIPS32_EF_SIZE
+
+#elif defined(CONFIG_64BIT)
+
+#define EF_R0			MIPS64_EF_R0
+#define EF_R1			MIPS64_EF_R1
+#define EF_R2			MIPS64_EF_R2
+#define EF_R3			MIPS64_EF_R3
+#define EF_R4			MIPS64_EF_R4
+#define EF_R5			MIPS64_EF_R5
+#define EF_R6			MIPS64_EF_R6
+#define EF_R7			MIPS64_EF_R7
+#define EF_R8			MIPS64_EF_R8
+#define EF_R9			MIPS64_EF_R9
+#define EF_R10			MIPS64_EF_R10
+#define EF_R11			MIPS64_EF_R11
+#define EF_R12			MIPS64_EF_R12
+#define EF_R13			MIPS64_EF_R13
+#define EF_R14			MIPS64_EF_R14
+#define EF_R15			MIPS64_EF_R15
+#define EF_R16			MIPS64_EF_R16
+#define EF_R17			MIPS64_EF_R17
+#define EF_R18			MIPS64_EF_R18
+#define EF_R19			MIPS64_EF_R19
+#define EF_R20			MIPS64_EF_R20
+#define EF_R21			MIPS64_EF_R21
+#define EF_R22			MIPS64_EF_R22
+#define EF_R23			MIPS64_EF_R23
+#define EF_R24			MIPS64_EF_R24
+#define EF_R25			MIPS64_EF_R25
+#define EF_R26			MIPS64_EF_R26
+#define EF_R27			MIPS64_EF_R27
+#define EF_R28			MIPS64_EF_R28
+#define EF_R29			MIPS64_EF_R29
+#define EF_R30			MIPS64_EF_R30
+#define EF_R31			MIPS64_EF_R31
+#define EF_LO			MIPS64_EF_LO
+#define EF_HI			MIPS64_EF_HI
+#define EF_CP0_EPC		MIPS64_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS64_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS64_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS64_EF_CP0_CAUSE
+#define EF_SIZE			MIPS64_EF_SIZE
 
 #endif /* CONFIG_64BIT */
 
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 7faf5f2..71df942 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -72,12 +72,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 #include <asm/processor.h>
 
-/*
- * When this file is selected, we are definitely running a 64bit kernel.
- * So using the right regs define in asm/reg.h
- */
-#define WANT_COMPAT_REG_H
-
 /* These MUST be defined before elf.h gets included */
 extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs);
 #define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
@@ -149,21 +143,21 @@ void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
 {
 	int i;
 
-	for (i = 0; i < EF_R0; i++)
+	for (i = 0; i < MIPS32_EF_R0; i++)
 		grp[i] = 0;
-	grp[EF_R0] = 0;
+	grp[MIPS32_EF_R0] = 0;
 	for (i = 1; i <= 31; i++)
-		grp[EF_R0 + i] = (elf_greg_t) regs->regs[i];
-	grp[EF_R26] = 0;
-	grp[EF_R27] = 0;
-	grp[EF_LO] = (elf_greg_t) regs->lo;
-	grp[EF_HI] = (elf_greg_t) regs->hi;
-	grp[EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
-	grp[EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
-	grp[EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
-	grp[EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
-#ifdef EF_UNUSED0
-	grp[EF_UNUSED0] = 0;
+		grp[MIPS32_EF_R0 + i] = (elf_greg_t) regs->regs[i];
+	grp[MIPS32_EF_R26] = 0;
+	grp[MIPS32_EF_R27] = 0;
+	grp[MIPS32_EF_LO] = (elf_greg_t) regs->lo;
+	grp[MIPS32_EF_HI] = (elf_greg_t) regs->hi;
+	grp[MIPS32_EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
+	grp[MIPS32_EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
+	grp[MIPS32_EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
+	grp[MIPS32_EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
+#ifdef MIPS32_EF_UNUSED0
+	grp[MIPS32_EF_UNUSED0] = 0;
 #endif
 }
 
-- 
1.9.1

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

* [PATCH 04/11] MIPS: ptrace: Change GP regset to use correct core dump register layout
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

Commit 6a9c001b7ec3 ("MIPS: Switch ELF core dumper to use regsets.")
switched the core dumper to use regsets, however the GP regset code
simply makes a direct copy of the kernel's pt_regs, which does not
match the original core dump register layout as defined in asm/reg.h.
Furthermore, the definition of pt_regs can vary with certain Kconfig
variables, therefore the GP regset can never be relied upon to return
registers in the same layout.

Therefore, this patch changes the GP regset to match the original core
dump layout. The layout differs for 32- and 64-bit processes, so
separate implementations of the get/set functions are added for the
32- and 64-bit regsets.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: <stable@vger.kernel.org> # v3.13+
---
 arch/mips/kernel/ptrace.c | 189 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 160 insertions(+), 29 deletions(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 8f2130a..8bd13ed 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -246,36 +246,160 @@ int ptrace_set_watch_regs(struct task_struct *child,
 
 /* regset get/set implementations */
 
-static int gpr_get(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   void *kbuf, void __user *ubuf)
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
+static int gpr32_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
 {
 	struct pt_regs *regs = task_pt_regs(target);
+	u32 uregs[ELF_NGREG] = {};
+	unsigned i;
+
+	for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) {
+		/* k0/k1 are copied as zero. */
+		if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27)
+			continue;
+
+		uregs[i] = regs->regs[i - MIPS32_EF_R0];
+	}
 
-	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				   regs, 0, sizeof(*regs));
+	uregs[MIPS32_EF_LO] = regs->lo;
+	uregs[MIPS32_EF_HI] = regs->hi;
+	uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc;
+	uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+	uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status;
+	uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				   sizeof(uregs));
 }
 
-static int gpr_set(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   const void *kbuf, const void __user *ubuf)
+static int gpr32_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
 {
-	struct pt_regs newregs;
-	int ret;
+	struct pt_regs *regs = task_pt_regs(target);
+	u32 uregs[ELF_NGREG];
+	unsigned start, num_regs, i;
+	int err;
+
+	start = pos / sizeof(u32);
+	num_regs = count / sizeof(u32);
+
+	if (start + num_regs > ELF_NGREG)
+		return -EIO;
+
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				 sizeof(uregs));
+	if (err)
+		return err;
+
+	for (i = start; i < num_regs; i++) {
+		/*
+		 * Cast all values to signed here so that if this is a 64-bit
+		 * kernel, the supplied 32-bit values will be sign extended.
+		 */
+		switch (i) {
+		case MIPS32_EF_R1 ... MIPS32_EF_R25:
+			/* k0/k1 are ignored. */
+		case MIPS32_EF_R28 ... MIPS32_EF_R31:
+			regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i];
+			break;
+		case MIPS32_EF_LO:
+			regs->lo = (s32)uregs[i];
+			break;
+		case MIPS32_EF_HI:
+			regs->hi = (s32)uregs[i];
+			break;
+		case MIPS32_EF_CP0_EPC:
+			regs->cp0_epc = (s32)uregs[i];
+			break;
+		}
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
+static int gpr64_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	u64 uregs[ELF_NGREG] = {};
+	unsigned i;
+
+	for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) {
+		/* k0/k1 are copied as zero. */
+		if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27)
+			continue;
+
+		uregs[i] = regs->regs[i - MIPS64_EF_R0];
+	}
+
+	uregs[MIPS64_EF_LO] = regs->lo;
+	uregs[MIPS64_EF_HI] = regs->hi;
+	uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc;
+	uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+	uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status;
+	uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				   sizeof(uregs));
+}
 
-	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &newregs,
-				 0, sizeof(newregs));
-	if (ret)
-		return ret;
+static int gpr64_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	u64 uregs[ELF_NGREG];
+	unsigned start, num_regs, i;
+	int err;
+
+	start = pos / sizeof(u64);
+	num_regs = count / sizeof(u64);
 
-	*task_pt_regs(target) = newregs;
+	if (start + num_regs > ELF_NGREG)
+		return -EIO;
+
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				 sizeof(uregs));
+	if (err)
+		return err;
+
+	for (i = start; i < num_regs; i++) {
+		switch (i) {
+		case MIPS64_EF_R1 ... MIPS64_EF_R25:
+			/* k0/k1 are ignored. */
+		case MIPS64_EF_R28 ... MIPS64_EF_R31:
+			regs->regs[i - MIPS64_EF_R0] = uregs[i];
+			break;
+		case MIPS64_EF_LO:
+			regs->lo = uregs[i];
+			break;
+		case MIPS64_EF_HI:
+			regs->hi = uregs[i];
+			break;
+		case MIPS64_EF_CP0_EPC:
+			regs->cp0_epc = uregs[i];
+			break;
+		}
+	}
 
 	return 0;
 }
 
+#endif /* CONFIG_64BIT */
+
 static int fpr_get(struct task_struct *target,
 		   const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
@@ -337,14 +461,16 @@ enum mips_regset {
 	REGSET_FPR,
 };
 
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
 static const struct user_regset mips_regsets[] = {
 	[REGSET_GPR] = {
 		.core_note_type	= NT_PRSTATUS,
 		.n		= ELF_NGREG,
 		.size		= sizeof(unsigned int),
 		.align		= sizeof(unsigned int),
-		.get		= gpr_get,
-		.set		= gpr_set,
+		.get		= gpr32_get,
+		.set		= gpr32_set,
 	},
 	[REGSET_FPR] = {
 		.core_note_type	= NT_PRFPREG,
@@ -364,14 +490,18 @@ static const struct user_regset_view user_mips_view = {
 	.n		= ARRAY_SIZE(mips_regsets),
 };
 
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
 static const struct user_regset mips64_regsets[] = {
 	[REGSET_GPR] = {
 		.core_note_type	= NT_PRSTATUS,
 		.n		= ELF_NGREG,
 		.size		= sizeof(unsigned long),
 		.align		= sizeof(unsigned long),
-		.get		= gpr_get,
-		.set		= gpr_set,
+		.get		= gpr64_get,
+		.set		= gpr64_set,
 	},
 	[REGSET_FPR] = {
 		.core_note_type	= NT_PRFPREG,
@@ -384,25 +514,26 @@ static const struct user_regset mips64_regsets[] = {
 };
 
 static const struct user_regset_view user_mips64_view = {
-	.name		= "mips",
+	.name		= "mips64",
 	.e_machine	= ELF_ARCH,
 	.ei_osabi	= ELF_OSABI,
 	.regsets	= mips64_regsets,
-	.n		= ARRAY_SIZE(mips_regsets),
+	.n		= ARRAY_SIZE(mips64_regsets),
 };
 
+#endif /* CONFIG_64BIT */
+
 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 {
 #ifdef CONFIG_32BIT
 	return &user_mips_view;
-#endif
-
+#else
 #ifdef CONFIG_MIPS32_O32
-		if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
-			return &user_mips_view;
+	if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
+		return &user_mips_view;
 #endif
-
 	return &user_mips64_view;
+#endif
 }
 
 long arch_ptrace(struct task_struct *child, long request,
-- 
1.9.1

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

* [PATCH 04/11] MIPS: ptrace: Change GP regset to use correct core dump register layout
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

Commit 6a9c001b7ec3 ("MIPS: Switch ELF core dumper to use regsets.")
switched the core dumper to use regsets, however the GP regset code
simply makes a direct copy of the kernel's pt_regs, which does not
match the original core dump register layout as defined in asm/reg.h.
Furthermore, the definition of pt_regs can vary with certain Kconfig
variables, therefore the GP regset can never be relied upon to return
registers in the same layout.

Therefore, this patch changes the GP regset to match the original core
dump layout. The layout differs for 32- and 64-bit processes, so
separate implementations of the get/set functions are added for the
32- and 64-bit regsets.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: <stable@vger.kernel.org> # v3.13+
---
 arch/mips/kernel/ptrace.c | 189 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 160 insertions(+), 29 deletions(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 8f2130a..8bd13ed 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -246,36 +246,160 @@ int ptrace_set_watch_regs(struct task_struct *child,
 
 /* regset get/set implementations */
 
-static int gpr_get(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   void *kbuf, void __user *ubuf)
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
+static int gpr32_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
 {
 	struct pt_regs *regs = task_pt_regs(target);
+	u32 uregs[ELF_NGREG] = {};
+	unsigned i;
+
+	for (i = MIPS32_EF_R1; i <= MIPS32_EF_R31; i++) {
+		/* k0/k1 are copied as zero. */
+		if (i == MIPS32_EF_R26 || i == MIPS32_EF_R27)
+			continue;
+
+		uregs[i] = regs->regs[i - MIPS32_EF_R0];
+	}
 
-	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-				   regs, 0, sizeof(*regs));
+	uregs[MIPS32_EF_LO] = regs->lo;
+	uregs[MIPS32_EF_HI] = regs->hi;
+	uregs[MIPS32_EF_CP0_EPC] = regs->cp0_epc;
+	uregs[MIPS32_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+	uregs[MIPS32_EF_CP0_STATUS] = regs->cp0_status;
+	uregs[MIPS32_EF_CP0_CAUSE] = regs->cp0_cause;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				   sizeof(uregs));
 }
 
-static int gpr_set(struct task_struct *target,
-		   const struct user_regset *regset,
-		   unsigned int pos, unsigned int count,
-		   const void *kbuf, const void __user *ubuf)
+static int gpr32_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
 {
-	struct pt_regs newregs;
-	int ret;
+	struct pt_regs *regs = task_pt_regs(target);
+	u32 uregs[ELF_NGREG];
+	unsigned start, num_regs, i;
+	int err;
+
+	start = pos / sizeof(u32);
+	num_regs = count / sizeof(u32);
+
+	if (start + num_regs > ELF_NGREG)
+		return -EIO;
+
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				 sizeof(uregs));
+	if (err)
+		return err;
+
+	for (i = start; i < num_regs; i++) {
+		/*
+		 * Cast all values to signed here so that if this is a 64-bit
+		 * kernel, the supplied 32-bit values will be sign extended.
+		 */
+		switch (i) {
+		case MIPS32_EF_R1 ... MIPS32_EF_R25:
+			/* k0/k1 are ignored. */
+		case MIPS32_EF_R28 ... MIPS32_EF_R31:
+			regs->regs[i - MIPS32_EF_R0] = (s32)uregs[i];
+			break;
+		case MIPS32_EF_LO:
+			regs->lo = (s32)uregs[i];
+			break;
+		case MIPS32_EF_HI:
+			regs->hi = (s32)uregs[i];
+			break;
+		case MIPS32_EF_CP0_EPC:
+			regs->cp0_epc = (s32)uregs[i];
+			break;
+		}
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
+static int gpr64_get(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     void *kbuf, void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	u64 uregs[ELF_NGREG] = {};
+	unsigned i;
+
+	for (i = MIPS64_EF_R1; i <= MIPS64_EF_R31; i++) {
+		/* k0/k1 are copied as zero. */
+		if (i == MIPS64_EF_R26 || i == MIPS64_EF_R27)
+			continue;
+
+		uregs[i] = regs->regs[i - MIPS64_EF_R0];
+	}
+
+	uregs[MIPS64_EF_LO] = regs->lo;
+	uregs[MIPS64_EF_HI] = regs->hi;
+	uregs[MIPS64_EF_CP0_EPC] = regs->cp0_epc;
+	uregs[MIPS64_EF_CP0_BADVADDR] = regs->cp0_badvaddr;
+	uregs[MIPS64_EF_CP0_STATUS] = regs->cp0_status;
+	uregs[MIPS64_EF_CP0_CAUSE] = regs->cp0_cause;
+
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				   sizeof(uregs));
+}
 
-	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-				 &newregs,
-				 0, sizeof(newregs));
-	if (ret)
-		return ret;
+static int gpr64_set(struct task_struct *target,
+		     const struct user_regset *regset,
+		     unsigned int pos, unsigned int count,
+		     const void *kbuf, const void __user *ubuf)
+{
+	struct pt_regs *regs = task_pt_regs(target);
+	u64 uregs[ELF_NGREG];
+	unsigned start, num_regs, i;
+	int err;
+
+	start = pos / sizeof(u64);
+	num_regs = count / sizeof(u64);
 
-	*task_pt_regs(target) = newregs;
+	if (start + num_regs > ELF_NGREG)
+		return -EIO;
+
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0,
+				 sizeof(uregs));
+	if (err)
+		return err;
+
+	for (i = start; i < num_regs; i++) {
+		switch (i) {
+		case MIPS64_EF_R1 ... MIPS64_EF_R25:
+			/* k0/k1 are ignored. */
+		case MIPS64_EF_R28 ... MIPS64_EF_R31:
+			regs->regs[i - MIPS64_EF_R0] = uregs[i];
+			break;
+		case MIPS64_EF_LO:
+			regs->lo = uregs[i];
+			break;
+		case MIPS64_EF_HI:
+			regs->hi = uregs[i];
+			break;
+		case MIPS64_EF_CP0_EPC:
+			regs->cp0_epc = uregs[i];
+			break;
+		}
+	}
 
 	return 0;
 }
 
+#endif /* CONFIG_64BIT */
+
 static int fpr_get(struct task_struct *target,
 		   const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
@@ -337,14 +461,16 @@ enum mips_regset {
 	REGSET_FPR,
 };
 
+#if defined(CONFIG_32BIT) || defined(CONFIG_MIPS32_O32)
+
 static const struct user_regset mips_regsets[] = {
 	[REGSET_GPR] = {
 		.core_note_type	= NT_PRSTATUS,
 		.n		= ELF_NGREG,
 		.size		= sizeof(unsigned int),
 		.align		= sizeof(unsigned int),
-		.get		= gpr_get,
-		.set		= gpr_set,
+		.get		= gpr32_get,
+		.set		= gpr32_set,
 	},
 	[REGSET_FPR] = {
 		.core_note_type	= NT_PRFPREG,
@@ -364,14 +490,18 @@ static const struct user_regset_view user_mips_view = {
 	.n		= ARRAY_SIZE(mips_regsets),
 };
 
+#endif /* CONFIG_32BIT || CONFIG_MIPS32_O32 */
+
+#ifdef CONFIG_64BIT
+
 static const struct user_regset mips64_regsets[] = {
 	[REGSET_GPR] = {
 		.core_note_type	= NT_PRSTATUS,
 		.n		= ELF_NGREG,
 		.size		= sizeof(unsigned long),
 		.align		= sizeof(unsigned long),
-		.get		= gpr_get,
-		.set		= gpr_set,
+		.get		= gpr64_get,
+		.set		= gpr64_set,
 	},
 	[REGSET_FPR] = {
 		.core_note_type	= NT_PRFPREG,
@@ -384,25 +514,26 @@ static const struct user_regset mips64_regsets[] = {
 };
 
 static const struct user_regset_view user_mips64_view = {
-	.name		= "mips",
+	.name		= "mips64",
 	.e_machine	= ELF_ARCH,
 	.ei_osabi	= ELF_OSABI,
 	.regsets	= mips64_regsets,
-	.n		= ARRAY_SIZE(mips_regsets),
+	.n		= ARRAY_SIZE(mips64_regsets),
 };
 
+#endif /* CONFIG_64BIT */
+
 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 {
 #ifdef CONFIG_32BIT
 	return &user_mips_view;
-#endif
-
+#else
 #ifdef CONFIG_MIPS32_O32
-		if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
-			return &user_mips_view;
+	if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
+		return &user_mips_view;
 #endif
-
 	return &user_mips64_view;
+#endif
 }
 
 long arch_ptrace(struct task_struct *child, long request,
-- 
1.9.1

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

* [PATCH 05/11] MIPS: ptrace: Always copy FCSR in FP regset
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, Paul Burton, stable

Copy FCSR in the FP regset to match the original pre-regset core dumper.
The code paths for where sizeof(union fpureg) == sizeof(elf_fpreg_t)
already do so, but they actually copy 4 bytes more than they should do
as FCSR is only 32 bits. The not equal code paths do not copy it at all.
Therefore change the copy to be done explicitly (with the correct size)
for both paths.

Additionally, clear the cause bits from FCSR when setting the FP regset
to avoid the possibility of causing an FP exception (and an oops) in the
kernel.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: <stable@vger.kernel.org> # v3.13+
---
This patch incorporates a fix for another instance of the bug fixed by
Paul Burton's patch "MIPS: prevent user from setting FCSR cause bits" -
the code path in fpr_set for sizeof(fpureg) == sizeof(elf_fpreg_t)
copied fcr31 without clearing cause bits. I've incorporated a fix for
it into this patch to so that it's easier to apply both patches without
conflicts.
---
 arch/mips/kernel/ptrace.c | 61 +++++++++++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 23 deletions(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 8bd13ed..ffc2e37 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -409,23 +409,28 @@ static int fpr_get(struct task_struct *target,
 	int err;
 	u64 fpr_val;
 
-	/* XXX fcr31  */
-
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					   &target->thread.fpu,
-					   0, sizeof(elf_fpregset_t));
-
-	for (i = 0; i < NUM_FPU_REGS; i++) {
-		fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
 		err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					  &fpr_val, i * sizeof(elf_fpreg_t),
-					  (i + 1) * sizeof(elf_fpreg_t));
+					  &target->thread.fpu.fpr,
+					  0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 		if (err)
 			return err;
+	} else {
+		for (i = 0; i < NUM_FPU_REGS; i++) {
+			fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+			err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+						  &fpr_val,
+						  i * sizeof(elf_fpreg_t),
+						  (i + 1) * sizeof(elf_fpreg_t));
+			if (err)
+				return err;
+		}
 	}
 
-	return 0;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			    &target->thread.fpu.fcr31,
+			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
 }
 
 static int fpr_set(struct task_struct *target,
@@ -436,23 +441,33 @@ static int fpr_set(struct task_struct *target,
 	unsigned i;
 	int err;
 	u64 fpr_val;
+	u32 fcr31;
 
-	/* XXX fcr31  */
-
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					  &target->thread.fpu,
-					  0, sizeof(elf_fpregset_t));
-
-	for (i = 0; i < NUM_FPU_REGS; i++) {
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
 		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					 &fpr_val, i * sizeof(elf_fpreg_t),
-					 (i + 1) * sizeof(elf_fpreg_t));
+					 &target->thread.fpu.fpr,
+					 0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 		if (err)
 			return err;
-		set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+	} else {
+		for (i = 0; i < NUM_FPU_REGS; i++) {
+			err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						 &fpr_val,
+						 i * sizeof(elf_fpreg_t),
+						 (i + 1) * sizeof(elf_fpreg_t));
+			if (err)
+				return err;
+			set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+		}
 	}
 
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31,
+			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
+	if (err)
+		return err;
+
+	target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;
 	return 0;
 }
 
-- 
1.9.1

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

* [PATCH 05/11] MIPS: ptrace: Always copy FCSR in FP regset
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, Paul Burton, stable

Copy FCSR in the FP regset to match the original pre-regset core dumper.
The code paths for where sizeof(union fpureg) == sizeof(elf_fpreg_t)
already do so, but they actually copy 4 bytes more than they should do
as FCSR is only 32 bits. The not equal code paths do not copy it at all.
Therefore change the copy to be done explicitly (with the correct size)
for both paths.

Additionally, clear the cause bits from FCSR when setting the FP regset
to avoid the possibility of causing an FP exception (and an oops) in the
kernel.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: <stable@vger.kernel.org> # v3.13+
---
This patch incorporates a fix for another instance of the bug fixed by
Paul Burton's patch "MIPS: prevent user from setting FCSR cause bits" -
the code path in fpr_set for sizeof(fpureg) == sizeof(elf_fpreg_t)
copied fcr31 without clearing cause bits. I've incorporated a fix for
it into this patch to so that it's easier to apply both patches without
conflicts.
---
 arch/mips/kernel/ptrace.c | 61 +++++++++++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 23 deletions(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 8bd13ed..ffc2e37 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -409,23 +409,28 @@ static int fpr_get(struct task_struct *target,
 	int err;
 	u64 fpr_val;
 
-	/* XXX fcr31  */
-
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					   &target->thread.fpu,
-					   0, sizeof(elf_fpregset_t));
-
-	for (i = 0; i < NUM_FPU_REGS; i++) {
-		fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
 		err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					  &fpr_val, i * sizeof(elf_fpreg_t),
-					  (i + 1) * sizeof(elf_fpreg_t));
+					  &target->thread.fpu.fpr,
+					  0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 		if (err)
 			return err;
+	} else {
+		for (i = 0; i < NUM_FPU_REGS; i++) {
+			fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+			err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+						  &fpr_val,
+						  i * sizeof(elf_fpreg_t),
+						  (i + 1) * sizeof(elf_fpreg_t));
+			if (err)
+				return err;
+		}
 	}
 
-	return 0;
+	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			    &target->thread.fpu.fcr31,
+			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
 }
 
 static int fpr_set(struct task_struct *target,
@@ -436,23 +441,33 @@ static int fpr_set(struct task_struct *target,
 	unsigned i;
 	int err;
 	u64 fpr_val;
+	u32 fcr31;
 
-	/* XXX fcr31  */
-
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					  &target->thread.fpu,
-					  0, sizeof(elf_fpregset_t));
-
-	for (i = 0; i < NUM_FPU_REGS; i++) {
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
 		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					 &fpr_val, i * sizeof(elf_fpreg_t),
-					 (i + 1) * sizeof(elf_fpreg_t));
+					 &target->thread.fpu.fpr,
+					 0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 		if (err)
 			return err;
-		set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+	} else {
+		for (i = 0; i < NUM_FPU_REGS; i++) {
+			err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						 &fpr_val,
+						 i * sizeof(elf_fpreg_t),
+						 (i + 1) * sizeof(elf_fpreg_t));
+			if (err)
+				return err;
+			set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+		}
 	}
 
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31,
+			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
+	if (err)
+		return err;
+
+	target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;
 	return 0;
 }
 
-- 
1.9.1

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

* [PATCH v2 06/11] MIPS: O32/32-bit: Fix bug which can cause incorrect system call restarts
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

From: Alex Smith <alex.smith@imgtec.com>

On 32-bit/O32, pt_regs has a padding area at the beginning into which the
syscall arguments passed via the user stack are copied. 4 arguments
totalling 16 bytes are copied to offset 16 bytes into this area, however
the area is only 24 bytes long. This means the last 2 arguments overwrite
pt_regs->regs[{0,1}].

If a syscall function returns an error, handle_sys stores the original
syscall number in pt_regs->regs[0] for syscall restart. signal.c checks
whether regs[0] is non-zero, if it is it will check whether the syscall
return value is one of the ERESTART* codes to see if it must be
restarted.

Should a syscall be made that results in a non-zero value being copied
off the user stack into regs[0], and then returns a positive (non-error)
value that matches one of the ERESTART* error codes, this can be mistaken
for requiring a syscall restart.

While the possibility for this to occur has always existed, it is made
much more likely to occur by commit 46e12c07b3b9 ("MIPS: O32 / 32-bit:
Always copy 4 stack arguments."), since now every syscall will copy 4
arguments and overwrite regs[0], rather than just those with 7 or 8
arguments.

Since that commit, booting Debian under a 32-bit MIPS kernel almost
always results in a hang early in boot, due to a wait4 syscall returning
a PID that matches one of the ERESTART* codes, which then causes an
incorrect restart of the syscall.

The problem is fixed by increasing the size of the padding area so that
arguments copied off the stack will not overwrite pt_regs->regs[{0,1}].

Signed-off-by: Alex Smith <alex.smith@imgtec.com>
Cc: <stable@vger.kernel.org> # v3.13+
---
Changes in v2:
 - Rebase on current upstream.
 - Split comment change into a separate commit.

I've rebased this patch on top of current mips-for-linux-next. However,
for it to be applied to stable it needs an additional change to the
PT_PADSLOT* definitions in arch/mips/kernel/smtc-asm.S to account for
the changed pt_regs offsets. This file no longer exists since SMTC has
been dropped.

I'm not sure what the correct way to deal with this is - can an
alternate version of the patch be submitted for stable?
---
 arch/mips/include/asm/ptrace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 7e6e682..c301fa9 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -23,7 +23,7 @@
 struct pt_regs {
 #ifdef CONFIG_32BIT
 	/* Pad bytes for argument save space on the stack. */
-	unsigned long pad0[6];
+	unsigned long pad0[8];
 #endif
 
 	/* Saved main processor registers. */
-- 
1.9.1

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

* [PATCH v2 06/11] MIPS: O32/32-bit: Fix bug which can cause incorrect system call restarts
@ 2014-07-23 13:40   ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, stable

From: Alex Smith <alex.smith@imgtec.com>

On 32-bit/O32, pt_regs has a padding area at the beginning into which the
syscall arguments passed via the user stack are copied. 4 arguments
totalling 16 bytes are copied to offset 16 bytes into this area, however
the area is only 24 bytes long. This means the last 2 arguments overwrite
pt_regs->regs[{0,1}].

If a syscall function returns an error, handle_sys stores the original
syscall number in pt_regs->regs[0] for syscall restart. signal.c checks
whether regs[0] is non-zero, if it is it will check whether the syscall
return value is one of the ERESTART* codes to see if it must be
restarted.

Should a syscall be made that results in a non-zero value being copied
off the user stack into regs[0], and then returns a positive (non-error)
value that matches one of the ERESTART* error codes, this can be mistaken
for requiring a syscall restart.

While the possibility for this to occur has always existed, it is made
much more likely to occur by commit 46e12c07b3b9 ("MIPS: O32 / 32-bit:
Always copy 4 stack arguments."), since now every syscall will copy 4
arguments and overwrite regs[0], rather than just those with 7 or 8
arguments.

Since that commit, booting Debian under a 32-bit MIPS kernel almost
always results in a hang early in boot, due to a wait4 syscall returning
a PID that matches one of the ERESTART* codes, which then causes an
incorrect restart of the syscall.

The problem is fixed by increasing the size of the padding area so that
arguments copied off the stack will not overwrite pt_regs->regs[{0,1}].

Signed-off-by: Alex Smith <alex.smith@imgtec.com>
Cc: <stable@vger.kernel.org> # v3.13+
---
Changes in v2:
 - Rebase on current upstream.
 - Split comment change into a separate commit.

I've rebased this patch on top of current mips-for-linux-next. However,
for it to be applied to stable it needs an additional change to the
PT_PADSLOT* definitions in arch/mips/kernel/smtc-asm.S to account for
the changed pt_regs offsets. This file no longer exists since SMTC has
been dropped.

I'm not sure what the correct way to deal with this is - can an
alternate version of the patch be submitted for stable?
---
 arch/mips/include/asm/ptrace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 7e6e682..c301fa9 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -23,7 +23,7 @@
 struct pt_regs {
 #ifdef CONFIG_32BIT
 	/* Pad bytes for argument save space on the stack. */
-	unsigned long pad0[6];
+	unsigned long pad0[8];
 #endif
 
 	/* Saved main processor registers. */
-- 
1.9.1

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

* [PATCH 07/11] MIPS: O32/32-bit: Remove outdated comment
  2014-07-23 13:40 [PATCH 00/11] MIPS ptrace/core dump fixes and cleanups Alex Smith
                   ` (5 preceding siblings ...)
  2014-07-23 13:40   ` Alex Smith
@ 2014-07-23 13:40 ` Alex Smith
  2014-07-23 13:40 ` [PATCH 08/11] MIPS: ptrace: Fix user pt_regs definition, use in ptrace_{get,set}regs() Alex Smith
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith

A comment in the O32/32-bit system call code is incorrect since commit
46e12c07b3b9 ("MIPS: O32 / 32-bit: Always copy 4 stack arguments.").
Remove it.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
---
 arch/mips/kernel/scall32-o32.S | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 3245474..63e8925 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -67,8 +67,6 @@ NESTED(handle_sys, PT_SIZE, sp)
 
 	/*
 	 * Ok, copy the args from the luser stack to the kernel stack.
-	 * t3 is the precomputed number of instruction bytes needed to
-	 * load or store arguments 6-8.
 	 */
 
 	.set    push
-- 
1.9.1

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

* [PATCH 08/11] MIPS: ptrace: Fix user pt_regs definition, use in ptrace_{get,set}regs()
  2014-07-23 13:40 [PATCH 00/11] MIPS ptrace/core dump fixes and cleanups Alex Smith
                   ` (6 preceding siblings ...)
  2014-07-23 13:40 ` [PATCH 07/11] MIPS: O32/32-bit: Remove outdated comment Alex Smith
@ 2014-07-23 13:40 ` Alex Smith
  2014-07-23 13:40 ` [PATCH 09/11] MIPS: Remove old core dump functions Alex Smith
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith

In uapi/asm/ptrace.h, a user version of pt_regs is defined wrapped in
ifndef __KERNEL__. This structure definition does not match anything
used by any kernel API, in particular it does not match the format used
by PTRACE_{GET,SET}REGS.

Therefore, replace the structure definition with one matching what is
used by PTRACE_{GET,SET}REGS. The format used by these is the same for
both 32-bit and 64-bit.

Also, change the implementation of PTRACE_{GET,SET}REGS to use this new
structure definition. The structure is renamed to user_pt_regs when
__KERNEL__ is defined to avoid conflicts with the kernel's own pt_regs.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
---
 arch/mips/include/asm/ptrace.h      |  6 ++++--
 arch/mips/include/uapi/asm/ptrace.h | 25 ++++++++++++++-----------
 arch/mips/kernel/ptrace.c           | 26 +++++++++++++-------------
 arch/mips/kernel/ptrace32.c         |  6 ++++--
 4 files changed, 35 insertions(+), 28 deletions(-)

diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index c301fa9..fc783f8 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -47,8 +47,10 @@ struct pt_regs {
 
 struct task_struct;
 
-extern int ptrace_getregs(struct task_struct *child, __s64 __user *data);
-extern int ptrace_setregs(struct task_struct *child, __s64 __user *data);
+extern int ptrace_getregs(struct task_struct *child,
+	struct user_pt_regs __user *data);
+extern int ptrace_setregs(struct task_struct *child,
+	struct user_pt_regs __user *data);
 
 extern int ptrace_getfpregs(struct task_struct *child, __u32 __user *data);
 extern int ptrace_setfpregs(struct task_struct *child, __u32 __user *data);
diff --git a/arch/mips/include/uapi/asm/ptrace.h b/arch/mips/include/uapi/asm/ptrace.h
index b26f7e3..bbcfb8b 100644
--- a/arch/mips/include/uapi/asm/ptrace.h
+++ b/arch/mips/include/uapi/asm/ptrace.h
@@ -22,24 +22,27 @@
 #define DSP_CONTROL	77
 #define ACX		78
 
-#ifndef __KERNEL__
 /*
- * This struct defines the way the registers are stored on the stack during a
- * system call/exception. As usual the registers k0/k1 aren't being saved.
+ * This struct defines the registers as used by PTRACE_{GET,SET}REGS. The
+ * format is the same for both 32- and 64-bit processes. Registers for 32-bit
+ * processes are sign extended.
  */
+#ifdef __KERNEL__
+struct user_pt_regs {
+#else
 struct pt_regs {
+#endif
 	/* Saved main processor registers. */
-	unsigned long regs[32];
+	__u64 regs[32];
 
 	/* Saved special registers. */
-	unsigned long cp0_status;
-	unsigned long hi;
-	unsigned long lo;
-	unsigned long cp0_badvaddr;
-	unsigned long cp0_cause;
-	unsigned long cp0_epc;
+	__u64 lo;
+	__u64 hi;
+	__u64 cp0_epc;
+	__u64 cp0_badvaddr;
+	__u64 cp0_status;
+	__u64 cp0_cause;
 } __attribute__ ((aligned (8)));
-#endif /* __KERNEL__ */
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS		12
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index ffc2e37..c0c582e 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -63,7 +63,7 @@ void ptrace_disable(struct task_struct *child)
  * for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
  * Registers are sign extended to fill the available space.
  */
-int ptrace_getregs(struct task_struct *child, __s64 __user *data)
+int ptrace_getregs(struct task_struct *child, struct user_pt_regs __user *data)
 {
 	struct pt_regs *regs;
 	int i;
@@ -74,13 +74,13 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
 	regs = task_pt_regs(child);
 
 	for (i = 0; i < 32; i++)
-		__put_user((long)regs->regs[i], data + i);
-	__put_user((long)regs->lo, data + EF_LO - EF_R0);
-	__put_user((long)regs->hi, data + EF_HI - EF_R0);
-	__put_user((long)regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
-	__put_user((long)regs->cp0_badvaddr, data + EF_CP0_BADVADDR - EF_R0);
-	__put_user((long)regs->cp0_status, data + EF_CP0_STATUS - EF_R0);
-	__put_user((long)regs->cp0_cause, data + EF_CP0_CAUSE - EF_R0);
+		__put_user((long)regs->regs[i], (__s64 __user *)&data->regs[i]);
+	__put_user((long)regs->lo, (__s64 __user *)&data->lo);
+	__put_user((long)regs->hi, (__s64 __user *)&data->hi);
+	__put_user((long)regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
+	__put_user((long)regs->cp0_badvaddr, (__s64 __user *)&data->cp0_badvaddr);
+	__put_user((long)regs->cp0_status, (__s64 __user *)&data->cp0_status);
+	__put_user((long)regs->cp0_cause, (__s64 __user *)&data->cp0_cause);
 
 	return 0;
 }
@@ -90,7 +90,7 @@ int ptrace_getregs(struct task_struct *child, __s64 __user *data)
  * the 64-bit format.  On a 32-bit kernel only the lower order half
  * (according to endianness) will be used.
  */
-int ptrace_setregs(struct task_struct *child, __s64 __user *data)
+int ptrace_setregs(struct task_struct *child, struct user_pt_regs __user *data)
 {
 	struct pt_regs *regs;
 	int i;
@@ -101,10 +101,10 @@ int ptrace_setregs(struct task_struct *child, __s64 __user *data)
 	regs = task_pt_regs(child);
 
 	for (i = 0; i < 32; i++)
-		__get_user(regs->regs[i], data + i);
-	__get_user(regs->lo, data + EF_LO - EF_R0);
-	__get_user(regs->hi, data + EF_HI - EF_R0);
-	__get_user(regs->cp0_epc, data + EF_CP0_EPC - EF_R0);
+		__get_user(regs->regs[i], (__s64 __user *)&data->regs[i]);
+	__get_user(regs->lo, (__s64 __user *)&data->lo);
+	__get_user(regs->hi, (__s64 __user *)&data->hi);
+	__get_user(regs->cp0_epc, (__s64 __user *)&data->cp0_epc);
 
 	/* badvaddr, status, and cause may not be written.  */
 
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index a83fb73..dee8729 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -256,11 +256,13 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 		}
 
 	case PTRACE_GETREGS:
-		ret = ptrace_getregs(child, (__s64 __user *) (__u64) data);
+		ret = ptrace_getregs(child,
+				(struct user_pt_regs __user *) (__u64) data);
 		break;
 
 	case PTRACE_SETREGS:
-		ret = ptrace_setregs(child, (__s64 __user *) (__u64) data);
+		ret = ptrace_setregs(child,
+				(struct user_pt_regs __user *) (__u64) data);
 		break;
 
 	case PTRACE_GETFPREGS:
-- 
1.9.1

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

* [PATCH 09/11] MIPS: Remove old core dump functions
  2014-07-23 13:40 [PATCH 00/11] MIPS ptrace/core dump fixes and cleanups Alex Smith
                   ` (7 preceding siblings ...)
  2014-07-23 13:40 ` [PATCH 08/11] MIPS: ptrace: Fix user pt_regs definition, use in ptrace_{get,set}regs() Alex Smith
@ 2014-07-23 13:40 ` Alex Smith
  2014-07-23 13:40 ` [PATCH 10/11] MIPS: Remove asm/user.h Alex Smith
  2014-07-23 13:40 ` [PATCH 11/11] MIPS: asm/reg.h: Move to uapi Alex Smith
  10 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith

Since the core dumper now uses regsets, the old core dump functions are
now unused. Remove them.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
---
 arch/mips/include/asm/elf.h      | 17 -------------
 arch/mips/kernel/binfmt_elfo32.c | 32 -----------------------
 arch/mips/kernel/process.c       | 55 ----------------------------------------
 3 files changed, 104 deletions(-)

diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h
index d414405..1d38fe0 100644
--- a/arch/mips/include/asm/elf.h
+++ b/arch/mips/include/asm/elf.h
@@ -339,23 +339,6 @@ do {									\
 
 #endif /* CONFIG_64BIT */
 
-struct pt_regs;
-struct task_struct;
-
-extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs);
-extern int dump_task_regs(struct task_struct *, elf_gregset_t *);
-extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *);
-
-#ifndef ELF_CORE_COPY_REGS
-#define ELF_CORE_COPY_REGS(elf_regs, regs)			\
-	elf_dump_regs((elf_greg_t *)&(elf_regs), regs);
-#endif
-#ifndef ELF_CORE_COPY_TASK_REGS
-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
-#endif
-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs)			\
-	dump_task_fpu(tsk, elf_fpregs)
-
 #define CORE_DUMP_USE_REGSET
 #define ELF_EXEC_PAGESIZE	PAGE_SIZE
 
diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
index 71df942..9287678 100644
--- a/arch/mips/kernel/binfmt_elfo32.c
+++ b/arch/mips/kernel/binfmt_elfo32.c
@@ -72,16 +72,6 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 #include <asm/processor.h>
 
-/* These MUST be defined before elf.h gets included */
-extern void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs);
-#define ELF_CORE_COPY_REGS(_dest, _regs) elf32_core_copy_regs(_dest, _regs);
-#define ELF_CORE_COPY_TASK_REGS(_tsk, _dest)				\
-({									\
-	int __res = 1;							\
-	elf32_core_copy_regs(*(_dest), task_pt_regs(_tsk));		\
-	__res;								\
-})
-
 #include <linux/module.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>
@@ -139,28 +129,6 @@ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
 	value->tv_usec = rem / NSEC_PER_USEC;
 }
 
-void elf32_core_copy_regs(elf_gregset_t grp, struct pt_regs *regs)
-{
-	int i;
-
-	for (i = 0; i < MIPS32_EF_R0; i++)
-		grp[i] = 0;
-	grp[MIPS32_EF_R0] = 0;
-	for (i = 1; i <= 31; i++)
-		grp[MIPS32_EF_R0 + i] = (elf_greg_t) regs->regs[i];
-	grp[MIPS32_EF_R26] = 0;
-	grp[MIPS32_EF_R27] = 0;
-	grp[MIPS32_EF_LO] = (elf_greg_t) regs->lo;
-	grp[MIPS32_EF_HI] = (elf_greg_t) regs->hi;
-	grp[MIPS32_EF_CP0_EPC] = (elf_greg_t) regs->cp0_epc;
-	grp[MIPS32_EF_CP0_BADVADDR] = (elf_greg_t) regs->cp0_badvaddr;
-	grp[MIPS32_EF_CP0_STATUS] = (elf_greg_t) regs->cp0_status;
-	grp[MIPS32_EF_CP0_CAUSE] = (elf_greg_t) regs->cp0_cause;
-#ifdef MIPS32_EF_UNUSED0
-	grp[MIPS32_EF_UNUSED0] = 0;
-#endif
-}
-
 MODULE_DESCRIPTION("Binary format loader for compatibility with o32 Linux/MIPS binaries");
 MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)");
 
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 0a1ec0f..7564c37 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -152,61 +152,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	return 0;
 }
 
-/* Fill in the fpu structure for a core dump.. */
-int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
-{
-	int i;
-
-	for (i = 0; i < NUM_FPU_REGS; i++)
-		memcpy(&r[i], &current->thread.fpu.fpr[i], sizeof(*r));
-
-	memcpy(&r[NUM_FPU_REGS], &current->thread.fpu.fcr31,
-	       sizeof(current->thread.fpu.fcr31));
-
-	return 1;
-}
-
-void elf_dump_regs(elf_greg_t *gp, struct pt_regs *regs)
-{
-	int i;
-
-	for (i = 0; i < EF_R0; i++)
-		gp[i] = 0;
-	gp[EF_R0] = 0;
-	for (i = 1; i <= 31; i++)
-		gp[EF_R0 + i] = regs->regs[i];
-	gp[EF_R26] = 0;
-	gp[EF_R27] = 0;
-	gp[EF_LO] = regs->lo;
-	gp[EF_HI] = regs->hi;
-	gp[EF_CP0_EPC] = regs->cp0_epc;
-	gp[EF_CP0_BADVADDR] = regs->cp0_badvaddr;
-	gp[EF_CP0_STATUS] = regs->cp0_status;
-	gp[EF_CP0_CAUSE] = regs->cp0_cause;
-#ifdef EF_UNUSED0
-	gp[EF_UNUSED0] = 0;
-#endif
-}
-
-int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
-{
-	elf_dump_regs(*regs, task_pt_regs(tsk));
-	return 1;
-}
-
-int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr)
-{
-	int i;
-
-	for (i = 0; i < NUM_FPU_REGS; i++)
-		memcpy(&fpr[i], &t->thread.fpu.fpr[i], sizeof(*fpr));
-
-	memcpy(&fpr[NUM_FPU_REGS], &t->thread.fpu.fcr31,
-	       sizeof(t->thread.fpu.fcr31));
-
-	return 1;
-}
-
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
 unsigned long __stack_chk_guard __read_mostly;
-- 
1.9.1

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

* [PATCH 10/11] MIPS: Remove asm/user.h
  2014-07-23 13:40 [PATCH 00/11] MIPS ptrace/core dump fixes and cleanups Alex Smith
                   ` (8 preceding siblings ...)
  2014-07-23 13:40 ` [PATCH 09/11] MIPS: Remove old core dump functions Alex Smith
@ 2014-07-23 13:40 ` Alex Smith
  2014-07-23 13:40 ` [PATCH 11/11] MIPS: asm/reg.h: Move to uapi Alex Smith
  10 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith

The struct user definition in this file is not used anywhere (the ELF
core dumper does not use that format). Therefore, remove the header and
instead enable the asm-generic user.h which is an empty header to
satisfy a few generic headers which still try to include user.h.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
---
 arch/mips/include/asm/Kbuild |  1 +
 arch/mips/include/asm/user.h | 58 --------------------------------------------
 arch/mips/kernel/process.c   |  2 +-
 arch/mips/kernel/ptrace.c    |  1 -
 arch/mips/kernel/ptrace32.c  |  2 +-
 5 files changed, 3 insertions(+), 61 deletions(-)
 delete mode 100644 arch/mips/include/asm/user.h

diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 0543918..335e529 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -15,4 +15,5 @@ generic-y += segment.h
 generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
+generic-y += user.h
 generic-y += xor.h
diff --git a/arch/mips/include/asm/user.h b/arch/mips/include/asm/user.h
deleted file mode 100644
index 6bad61b..0000000
--- a/arch/mips/include/asm/user.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994, 1995, 1996, 1999 by Ralf Baechle
- */
-#ifndef _ASM_USER_H
-#define _ASM_USER_H
-
-#include <asm/page.h>
-#include <asm/reg.h>
-
-/*
- * Core file format: The core file is written in such a way that gdb
- * can understand it and provide useful information to the user (under
- * linux we use the `trad-core' bfd, NOT the irix-core).  The file
- * contents are as follows:
- *
- *  upage: 1 page consisting of a user struct that tells gdb
- *	what is present in the file.  Directly after this is a
- *	copy of the task_struct, which is currently not used by gdb,
- *	but it may come in handy at some point.	 All of the registers
- *	are stored as part of the upage.  The upage should always be
- *	only one page long.
- *  data: The data segment follows next.  We use current->end_text to
- *	current->brk to pick up all of the user variables, plus any memory
- *	that may have been sbrk'ed.  No attempt is made to determine if a
- *	page is demand-zero or if a page is totally unused, we just cover
- *	the entire range.  All of the addresses are rounded in such a way
- *	that an integral number of pages is written.
- *  stack: We need the stack information in order to get a meaningful
- *	backtrace.  We need to write the data from usp to
- *	current->start_stack, so we round each of these in order to be able
- *	to write an integer number of pages.
- */
-struct user {
-	unsigned long	regs[EF_SIZE /		/* integer and fp regs */
-			sizeof(unsigned long) + 64];
-	size_t		u_tsize;		/* text size (pages) */
-	size_t		u_dsize;		/* data size (pages) */
-	size_t		u_ssize;		/* stack size (pages) */
-	unsigned long	start_code;		/* text starting address */
-	unsigned long	start_data;		/* data starting address */
-	unsigned long	start_stack;		/* stack starting address */
-	long int	signal;			/* signal causing core dump */
-	unsigned long	u_ar0;			/* help gdb find registers */
-	unsigned long	magic;			/* identifies a core file */
-	char		u_comm[32];		/* user command name */
-};
-
-#define NBPG			PAGE_SIZE
-#define UPAGES			1
-#define HOST_TEXT_START_ADDR	(u.start_code)
-#define HOST_DATA_START_ADDR	(u.start_data)
-#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
-
-#endif /* _ASM_USER_H */
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 7564c37..2dafceb 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -21,7 +21,6 @@
 #include <linux/mman.h>
 #include <linux/personality.h>
 #include <linux/sys.h>
-#include <linux/user.h>
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/kallsyms.h>
@@ -36,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
+#include <asm/reg.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/elf.h>
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index c0c582e..ea99743 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -24,7 +24,6 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/smp.h>
-#include <linux/user.h>
 #include <linux/security.h>
 #include <linux/tracehook.h>
 #include <linux/audit.h>
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index dee8729..283b5a1 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -22,7 +22,6 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/smp.h>
-#include <linux/user.h>
 #include <linux/security.h>
 
 #include <asm/cpu.h>
@@ -32,6 +31,7 @@
 #include <asm/mipsmtregs.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/reg.h>
 #include <asm/uaccess.h>
 #include <asm/bootinfo.h>
 
-- 
1.9.1

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

* [PATCH 11/11] MIPS: asm/reg.h: Move to uapi
  2014-07-23 13:40 [PATCH 00/11] MIPS ptrace/core dump fixes and cleanups Alex Smith
                   ` (9 preceding siblings ...)
  2014-07-23 13:40 ` [PATCH 10/11] MIPS: Remove asm/user.h Alex Smith
@ 2014-07-23 13:40 ` Alex Smith
  10 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 13:40 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith

This header defines an exported interface (the register layout used in
core dumps and the GP regset accessible with PTRACE_{GET,SET}REGSET),
therefore belongs in uapi.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
---
 arch/mips/include/asm/reg.h      | 207 +--------------------------------------
 arch/mips/include/uapi/asm/reg.h | 206 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+), 206 deletions(-)
 create mode 100644 arch/mips/include/uapi/asm/reg.h

diff --git a/arch/mips/include/asm/reg.h b/arch/mips/include/asm/reg.h
index b8343cc..84dc7e2 100644
--- a/arch/mips/include/asm/reg.h
+++ b/arch/mips/include/asm/reg.h
@@ -1,206 +1 @@
-/*
- * Various register offset definitions for debuggers, core file
- * examiners and whatnot.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1999 Ralf Baechle
- * Copyright (C) 1995, 1999 Silicon Graphics
- */
-#ifndef __ASM_MIPS_REG_H
-#define __ASM_MIPS_REG_H
-
-#define MIPS32_EF_R0		6
-#define MIPS32_EF_R1		7
-#define MIPS32_EF_R2		8
-#define MIPS32_EF_R3		9
-#define MIPS32_EF_R4		10
-#define MIPS32_EF_R5		11
-#define MIPS32_EF_R6		12
-#define MIPS32_EF_R7		13
-#define MIPS32_EF_R8		14
-#define MIPS32_EF_R9		15
-#define MIPS32_EF_R10		16
-#define MIPS32_EF_R11		17
-#define MIPS32_EF_R12		18
-#define MIPS32_EF_R13		19
-#define MIPS32_EF_R14		20
-#define MIPS32_EF_R15		21
-#define MIPS32_EF_R16		22
-#define MIPS32_EF_R17		23
-#define MIPS32_EF_R18		24
-#define MIPS32_EF_R19		25
-#define MIPS32_EF_R20		26
-#define MIPS32_EF_R21		27
-#define MIPS32_EF_R22		28
-#define MIPS32_EF_R23		29
-#define MIPS32_EF_R24		30
-#define MIPS32_EF_R25		31
-
-/*
- * k0/k1 unsaved
- */
-#define MIPS32_EF_R26		32
-#define MIPS32_EF_R27		33
-
-#define MIPS32_EF_R28		34
-#define MIPS32_EF_R29		35
-#define MIPS32_EF_R30		36
-#define MIPS32_EF_R31		37
-
-/*
- * Saved special registers
- */
-#define MIPS32_EF_LO		38
-#define MIPS32_EF_HI		39
-
-#define MIPS32_EF_CP0_EPC	40
-#define MIPS32_EF_CP0_BADVADDR	41
-#define MIPS32_EF_CP0_STATUS	42
-#define MIPS32_EF_CP0_CAUSE	43
-#define MIPS32_EF_UNUSED0	44
-
-#define MIPS32_EF_SIZE		180
-
-#define MIPS64_EF_R0		0
-#define MIPS64_EF_R1		1
-#define MIPS64_EF_R2		2
-#define MIPS64_EF_R3		3
-#define MIPS64_EF_R4		4
-#define MIPS64_EF_R5		5
-#define MIPS64_EF_R6		6
-#define MIPS64_EF_R7		7
-#define MIPS64_EF_R8		8
-#define MIPS64_EF_R9		9
-#define MIPS64_EF_R10		10
-#define MIPS64_EF_R11		11
-#define MIPS64_EF_R12		12
-#define MIPS64_EF_R13		13
-#define MIPS64_EF_R14		14
-#define MIPS64_EF_R15		15
-#define MIPS64_EF_R16		16
-#define MIPS64_EF_R17		17
-#define MIPS64_EF_R18		18
-#define MIPS64_EF_R19		19
-#define MIPS64_EF_R20		20
-#define MIPS64_EF_R21		21
-#define MIPS64_EF_R22		22
-#define MIPS64_EF_R23		23
-#define MIPS64_EF_R24		24
-#define MIPS64_EF_R25		25
-
-/*
- * k0/k1 unsaved
- */
-#define MIPS64_EF_R26		26
-#define MIPS64_EF_R27		27
-
-
-#define MIPS64_EF_R28		28
-#define MIPS64_EF_R29		29
-#define MIPS64_EF_R30		30
-#define MIPS64_EF_R31		31
-
-/*
- * Saved special registers
- */
-#define MIPS64_EF_LO		32
-#define MIPS64_EF_HI		33
-
-#define MIPS64_EF_CP0_EPC	34
-#define MIPS64_EF_CP0_BADVADDR	35
-#define MIPS64_EF_CP0_STATUS	36
-#define MIPS64_EF_CP0_CAUSE	37
-
-#define MIPS64_EF_SIZE		304	/* size in bytes */
-
-#if defined(CONFIG_32BIT)
-
-#define EF_R0			MIPS32_EF_R0
-#define EF_R1			MIPS32_EF_R1
-#define EF_R2			MIPS32_EF_R2
-#define EF_R3			MIPS32_EF_R3
-#define EF_R4			MIPS32_EF_R4
-#define EF_R5			MIPS32_EF_R5
-#define EF_R6			MIPS32_EF_R6
-#define EF_R7			MIPS32_EF_R7
-#define EF_R8			MIPS32_EF_R8
-#define EF_R9			MIPS32_EF_R9
-#define EF_R10			MIPS32_EF_R10
-#define EF_R11			MIPS32_EF_R11
-#define EF_R12			MIPS32_EF_R12
-#define EF_R13			MIPS32_EF_R13
-#define EF_R14			MIPS32_EF_R14
-#define EF_R15			MIPS32_EF_R15
-#define EF_R16			MIPS32_EF_R16
-#define EF_R17			MIPS32_EF_R17
-#define EF_R18			MIPS32_EF_R18
-#define EF_R19			MIPS32_EF_R19
-#define EF_R20			MIPS32_EF_R20
-#define EF_R21			MIPS32_EF_R21
-#define EF_R22			MIPS32_EF_R22
-#define EF_R23			MIPS32_EF_R23
-#define EF_R24			MIPS32_EF_R24
-#define EF_R25			MIPS32_EF_R25
-#define EF_R26			MIPS32_EF_R26
-#define EF_R27			MIPS32_EF_R27
-#define EF_R28			MIPS32_EF_R28
-#define EF_R29			MIPS32_EF_R29
-#define EF_R30			MIPS32_EF_R30
-#define EF_R31			MIPS32_EF_R31
-#define EF_LO			MIPS32_EF_LO
-#define EF_HI			MIPS32_EF_HI
-#define EF_CP0_EPC		MIPS32_EF_CP0_EPC
-#define EF_CP0_BADVADDR		MIPS32_EF_CP0_BADVADDR
-#define EF_CP0_STATUS		MIPS32_EF_CP0_STATUS
-#define EF_CP0_CAUSE		MIPS32_EF_CP0_CAUSE
-#define EF_UNUSED0		MIPS32_EF_UNUSED0
-#define EF_SIZE			MIPS32_EF_SIZE
-
-#elif defined(CONFIG_64BIT)
-
-#define EF_R0			MIPS64_EF_R0
-#define EF_R1			MIPS64_EF_R1
-#define EF_R2			MIPS64_EF_R2
-#define EF_R3			MIPS64_EF_R3
-#define EF_R4			MIPS64_EF_R4
-#define EF_R5			MIPS64_EF_R5
-#define EF_R6			MIPS64_EF_R6
-#define EF_R7			MIPS64_EF_R7
-#define EF_R8			MIPS64_EF_R8
-#define EF_R9			MIPS64_EF_R9
-#define EF_R10			MIPS64_EF_R10
-#define EF_R11			MIPS64_EF_R11
-#define EF_R12			MIPS64_EF_R12
-#define EF_R13			MIPS64_EF_R13
-#define EF_R14			MIPS64_EF_R14
-#define EF_R15			MIPS64_EF_R15
-#define EF_R16			MIPS64_EF_R16
-#define EF_R17			MIPS64_EF_R17
-#define EF_R18			MIPS64_EF_R18
-#define EF_R19			MIPS64_EF_R19
-#define EF_R20			MIPS64_EF_R20
-#define EF_R21			MIPS64_EF_R21
-#define EF_R22			MIPS64_EF_R22
-#define EF_R23			MIPS64_EF_R23
-#define EF_R24			MIPS64_EF_R24
-#define EF_R25			MIPS64_EF_R25
-#define EF_R26			MIPS64_EF_R26
-#define EF_R27			MIPS64_EF_R27
-#define EF_R28			MIPS64_EF_R28
-#define EF_R29			MIPS64_EF_R29
-#define EF_R30			MIPS64_EF_R30
-#define EF_R31			MIPS64_EF_R31
-#define EF_LO			MIPS64_EF_LO
-#define EF_HI			MIPS64_EF_HI
-#define EF_CP0_EPC		MIPS64_EF_CP0_EPC
-#define EF_CP0_BADVADDR		MIPS64_EF_CP0_BADVADDR
-#define EF_CP0_STATUS		MIPS64_EF_CP0_STATUS
-#define EF_CP0_CAUSE		MIPS64_EF_CP0_CAUSE
-#define EF_SIZE			MIPS64_EF_SIZE
-
-#endif /* CONFIG_64BIT */
-
-#endif /* __ASM_MIPS_REG_H */
+#include <uapi/asm/reg.h>
diff --git a/arch/mips/include/uapi/asm/reg.h b/arch/mips/include/uapi/asm/reg.h
new file mode 100644
index 0000000..432037c
--- /dev/null
+++ b/arch/mips/include/uapi/asm/reg.h
@@ -0,0 +1,206 @@
+/*
+ * Various register offset definitions for debuggers, core file
+ * examiners and whatnot.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1999 Ralf Baechle
+ * Copyright (C) 1995, 1999 Silicon Graphics
+ */
+#ifndef __UAPI_ASM_MIPS_REG_H
+#define __UAPI_ASM_MIPS_REG_H
+
+#define MIPS32_EF_R0		6
+#define MIPS32_EF_R1		7
+#define MIPS32_EF_R2		8
+#define MIPS32_EF_R3		9
+#define MIPS32_EF_R4		10
+#define MIPS32_EF_R5		11
+#define MIPS32_EF_R6		12
+#define MIPS32_EF_R7		13
+#define MIPS32_EF_R8		14
+#define MIPS32_EF_R9		15
+#define MIPS32_EF_R10		16
+#define MIPS32_EF_R11		17
+#define MIPS32_EF_R12		18
+#define MIPS32_EF_R13		19
+#define MIPS32_EF_R14		20
+#define MIPS32_EF_R15		21
+#define MIPS32_EF_R16		22
+#define MIPS32_EF_R17		23
+#define MIPS32_EF_R18		24
+#define MIPS32_EF_R19		25
+#define MIPS32_EF_R20		26
+#define MIPS32_EF_R21		27
+#define MIPS32_EF_R22		28
+#define MIPS32_EF_R23		29
+#define MIPS32_EF_R24		30
+#define MIPS32_EF_R25		31
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS32_EF_R26		32
+#define MIPS32_EF_R27		33
+
+#define MIPS32_EF_R28		34
+#define MIPS32_EF_R29		35
+#define MIPS32_EF_R30		36
+#define MIPS32_EF_R31		37
+
+/*
+ * Saved special registers
+ */
+#define MIPS32_EF_LO		38
+#define MIPS32_EF_HI		39
+
+#define MIPS32_EF_CP0_EPC	40
+#define MIPS32_EF_CP0_BADVADDR	41
+#define MIPS32_EF_CP0_STATUS	42
+#define MIPS32_EF_CP0_CAUSE	43
+#define MIPS32_EF_UNUSED0	44
+
+#define MIPS32_EF_SIZE		180
+
+#define MIPS64_EF_R0		0
+#define MIPS64_EF_R1		1
+#define MIPS64_EF_R2		2
+#define MIPS64_EF_R3		3
+#define MIPS64_EF_R4		4
+#define MIPS64_EF_R5		5
+#define MIPS64_EF_R6		6
+#define MIPS64_EF_R7		7
+#define MIPS64_EF_R8		8
+#define MIPS64_EF_R9		9
+#define MIPS64_EF_R10		10
+#define MIPS64_EF_R11		11
+#define MIPS64_EF_R12		12
+#define MIPS64_EF_R13		13
+#define MIPS64_EF_R14		14
+#define MIPS64_EF_R15		15
+#define MIPS64_EF_R16		16
+#define MIPS64_EF_R17		17
+#define MIPS64_EF_R18		18
+#define MIPS64_EF_R19		19
+#define MIPS64_EF_R20		20
+#define MIPS64_EF_R21		21
+#define MIPS64_EF_R22		22
+#define MIPS64_EF_R23		23
+#define MIPS64_EF_R24		24
+#define MIPS64_EF_R25		25
+
+/*
+ * k0/k1 unsaved
+ */
+#define MIPS64_EF_R26		26
+#define MIPS64_EF_R27		27
+
+
+#define MIPS64_EF_R28		28
+#define MIPS64_EF_R29		29
+#define MIPS64_EF_R30		30
+#define MIPS64_EF_R31		31
+
+/*
+ * Saved special registers
+ */
+#define MIPS64_EF_LO		32
+#define MIPS64_EF_HI		33
+
+#define MIPS64_EF_CP0_EPC	34
+#define MIPS64_EF_CP0_BADVADDR	35
+#define MIPS64_EF_CP0_STATUS	36
+#define MIPS64_EF_CP0_CAUSE	37
+
+#define MIPS64_EF_SIZE		304	/* size in bytes */
+
+#if _MIPS_SIM == _MIPS_SIM_ABI32
+
+#define EF_R0			MIPS32_EF_R0
+#define EF_R1			MIPS32_EF_R1
+#define EF_R2			MIPS32_EF_R2
+#define EF_R3			MIPS32_EF_R3
+#define EF_R4			MIPS32_EF_R4
+#define EF_R5			MIPS32_EF_R5
+#define EF_R6			MIPS32_EF_R6
+#define EF_R7			MIPS32_EF_R7
+#define EF_R8			MIPS32_EF_R8
+#define EF_R9			MIPS32_EF_R9
+#define EF_R10			MIPS32_EF_R10
+#define EF_R11			MIPS32_EF_R11
+#define EF_R12			MIPS32_EF_R12
+#define EF_R13			MIPS32_EF_R13
+#define EF_R14			MIPS32_EF_R14
+#define EF_R15			MIPS32_EF_R15
+#define EF_R16			MIPS32_EF_R16
+#define EF_R17			MIPS32_EF_R17
+#define EF_R18			MIPS32_EF_R18
+#define EF_R19			MIPS32_EF_R19
+#define EF_R20			MIPS32_EF_R20
+#define EF_R21			MIPS32_EF_R21
+#define EF_R22			MIPS32_EF_R22
+#define EF_R23			MIPS32_EF_R23
+#define EF_R24			MIPS32_EF_R24
+#define EF_R25			MIPS32_EF_R25
+#define EF_R26			MIPS32_EF_R26
+#define EF_R27			MIPS32_EF_R27
+#define EF_R28			MIPS32_EF_R28
+#define EF_R29			MIPS32_EF_R29
+#define EF_R30			MIPS32_EF_R30
+#define EF_R31			MIPS32_EF_R31
+#define EF_LO			MIPS32_EF_LO
+#define EF_HI			MIPS32_EF_HI
+#define EF_CP0_EPC		MIPS32_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS32_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS32_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS32_EF_CP0_CAUSE
+#define EF_UNUSED0		MIPS32_EF_UNUSED0
+#define EF_SIZE			MIPS32_EF_SIZE
+
+#elif _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32
+
+#define EF_R0			MIPS64_EF_R0
+#define EF_R1			MIPS64_EF_R1
+#define EF_R2			MIPS64_EF_R2
+#define EF_R3			MIPS64_EF_R3
+#define EF_R4			MIPS64_EF_R4
+#define EF_R5			MIPS64_EF_R5
+#define EF_R6			MIPS64_EF_R6
+#define EF_R7			MIPS64_EF_R7
+#define EF_R8			MIPS64_EF_R8
+#define EF_R9			MIPS64_EF_R9
+#define EF_R10			MIPS64_EF_R10
+#define EF_R11			MIPS64_EF_R11
+#define EF_R12			MIPS64_EF_R12
+#define EF_R13			MIPS64_EF_R13
+#define EF_R14			MIPS64_EF_R14
+#define EF_R15			MIPS64_EF_R15
+#define EF_R16			MIPS64_EF_R16
+#define EF_R17			MIPS64_EF_R17
+#define EF_R18			MIPS64_EF_R18
+#define EF_R19			MIPS64_EF_R19
+#define EF_R20			MIPS64_EF_R20
+#define EF_R21			MIPS64_EF_R21
+#define EF_R22			MIPS64_EF_R22
+#define EF_R23			MIPS64_EF_R23
+#define EF_R24			MIPS64_EF_R24
+#define EF_R25			MIPS64_EF_R25
+#define EF_R26			MIPS64_EF_R26
+#define EF_R27			MIPS64_EF_R27
+#define EF_R28			MIPS64_EF_R28
+#define EF_R29			MIPS64_EF_R29
+#define EF_R30			MIPS64_EF_R30
+#define EF_R31			MIPS64_EF_R31
+#define EF_LO			MIPS64_EF_LO
+#define EF_HI			MIPS64_EF_HI
+#define EF_CP0_EPC		MIPS64_EF_CP0_EPC
+#define EF_CP0_BADVADDR		MIPS64_EF_CP0_BADVADDR
+#define EF_CP0_STATUS		MIPS64_EF_CP0_STATUS
+#define EF_CP0_CAUSE		MIPS64_EF_CP0_CAUSE
+#define EF_SIZE			MIPS64_EF_SIZE
+
+#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32 */
+
+#endif /* __UAPI_ASM_MIPS_REG_H */
-- 
1.9.1

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

* Re: [PATCH 05/11] MIPS: ptrace: Always copy FCSR in FP regset
@ 2014-07-23 14:12     ` Paul Burton
  0 siblings, 0 replies; 25+ messages in thread
From: Paul Burton @ 2014-07-23 14:12 UTC (permalink / raw)
  To: Alex Smith; +Cc: linux-mips, stable

On Wed, Jul 23, 2014 at 02:40:10PM +0100, Alex Smith wrote:
> Copy FCSR in the FP regset to match the original pre-regset core dumper.
> The code paths for where sizeof(union fpureg) == sizeof(elf_fpreg_t)
> already do so, but they actually copy 4 bytes more than they should do
> as FCSR is only 32 bits. The not equal code paths do not copy it at all.
> Therefore change the copy to be done explicitly (with the correct size)
> for both paths.

Ah, I hadn't realised that ELF_NFPREG == 33, sneaky! That together with
the "XXX fcr31" comment led me to believe the FP regset didn't include
FCSR which is why I hadn't fixed the oops there or taken it into account
for the case where FPR size != sizeof(elf_fpreg_t) (ie. when MSA support
is enabled).

> Additionally, clear the cause bits from FCSR when setting the FP regset
> to avoid the possibility of causing an FP exception (and an oops) in the
> kernel.
> 
> Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Cc: <stable@vger.kernel.org> # v3.13+
> ---
> This patch incorporates a fix for another instance of the bug fixed by
> Paul Burton's patch "MIPS: prevent user from setting FCSR cause bits" -
> the code path in fpr_set for sizeof(fpureg) == sizeof(elf_fpreg_t)
> copied fcr31 without clearing cause bits. I've incorporated a fix for
> it into this patch to so that it's easier to apply both patches without
> conflicts.
> ---
>  arch/mips/kernel/ptrace.c | 61 +++++++++++++++++++++++++++++------------------
>  1 file changed, 38 insertions(+), 23 deletions(-)
> 
> diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
> index 8bd13ed..ffc2e37 100644
> --- a/arch/mips/kernel/ptrace.c
> +++ b/arch/mips/kernel/ptrace.c
> @@ -409,23 +409,28 @@ static int fpr_get(struct task_struct *target,
>  	int err;
>  	u64 fpr_val;
>  
> -	/* XXX fcr31  */
> -
> -	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
> -		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
> -					   &target->thread.fpu,
> -					   0, sizeof(elf_fpregset_t));
> -
> -	for (i = 0; i < NUM_FPU_REGS; i++) {
> -		fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
> +	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
>  		err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
> -					  &fpr_val, i * sizeof(elf_fpreg_t),
> -					  (i + 1) * sizeof(elf_fpreg_t));
> +					  &target->thread.fpu.fpr,
> +					  0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
>  		if (err)
>  			return err;
> +	} else {
> +		for (i = 0; i < NUM_FPU_REGS; i++) {
> +			fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
> +			err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
> +						  &fpr_val,
> +						  i * sizeof(elf_fpreg_t),
> +						  (i + 1) * sizeof(elf_fpreg_t));
> +			if (err)
> +				return err;
> +		}
>  	}
>  
> -	return 0;
> +	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
> +			    &target->thread.fpu.fcr31,
> +			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
> +			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));

The only problem I can think of is that the final register in the regset
will still be treated as 64b (regset->size) as far as ptrace is
concerned, so I'm not sure how best to handle this. I presume the pre
regset core dump format placed the 32b FCSR value immediately after
the 64b $f31, as you have here? In which case we should probably at
least zero out the other 4 bytes of this final "register", assuming
the extra 4 bytes compared to the pre-regset version isn't a problem?

Thanks,
    Paul

>  }
>  
>  static int fpr_set(struct task_struct *target,
> @@ -436,23 +441,33 @@ static int fpr_set(struct task_struct *target,
>  	unsigned i;
>  	int err;
>  	u64 fpr_val;
> +	u32 fcr31;
>  
> -	/* XXX fcr31  */
> -
> -	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
> -		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
> -					  &target->thread.fpu,
> -					  0, sizeof(elf_fpregset_t));
> -
> -	for (i = 0; i < NUM_FPU_REGS; i++) {
> +	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
>  		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
> -					 &fpr_val, i * sizeof(elf_fpreg_t),
> -					 (i + 1) * sizeof(elf_fpreg_t));
> +					 &target->thread.fpu.fpr,
> +					 0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
>  		if (err)
>  			return err;
> -		set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
> +	} else {
> +		for (i = 0; i < NUM_FPU_REGS; i++) {
> +			err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
> +						 &fpr_val,
> +						 i * sizeof(elf_fpreg_t),
> +						 (i + 1) * sizeof(elf_fpreg_t));
> +			if (err)
> +				return err;
> +			set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
> +		}
>  	}
>  
> +	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31,
> +			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
> +			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
> +	if (err)
> +		return err;
> +
> +	target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;
>  	return 0;
>  }
>  
> -- 
> 1.9.1
> 

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

* Re: [PATCH 05/11] MIPS: ptrace: Always copy FCSR in FP regset
@ 2014-07-23 14:12     ` Paul Burton
  0 siblings, 0 replies; 25+ messages in thread
From: Paul Burton @ 2014-07-23 14:12 UTC (permalink / raw)
  To: Alex Smith; +Cc: linux-mips, stable

On Wed, Jul 23, 2014 at 02:40:10PM +0100, Alex Smith wrote:
> Copy FCSR in the FP regset to match the original pre-regset core dumper.
> The code paths for where sizeof(union fpureg) == sizeof(elf_fpreg_t)
> already do so, but they actually copy 4 bytes more than they should do
> as FCSR is only 32 bits. The not equal code paths do not copy it at all.
> Therefore change the copy to be done explicitly (with the correct size)
> for both paths.

Ah, I hadn't realised that ELF_NFPREG == 33, sneaky! That together with
the "XXX fcr31" comment led me to believe the FP regset didn't include
FCSR which is why I hadn't fixed the oops there or taken it into account
for the case where FPR size != sizeof(elf_fpreg_t) (ie. when MSA support
is enabled).

> Additionally, clear the cause bits from FCSR when setting the FP regset
> to avoid the possibility of causing an FP exception (and an oops) in the
> kernel.
> 
> Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
> Cc: Paul Burton <paul.burton@imgtec.com>
> Cc: <stable@vger.kernel.org> # v3.13+
> ---
> This patch incorporates a fix for another instance of the bug fixed by
> Paul Burton's patch "MIPS: prevent user from setting FCSR cause bits" -
> the code path in fpr_set for sizeof(fpureg) == sizeof(elf_fpreg_t)
> copied fcr31 without clearing cause bits. I've incorporated a fix for
> it into this patch to so that it's easier to apply both patches without
> conflicts.
> ---
>  arch/mips/kernel/ptrace.c | 61 +++++++++++++++++++++++++++++------------------
>  1 file changed, 38 insertions(+), 23 deletions(-)
> 
> diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
> index 8bd13ed..ffc2e37 100644
> --- a/arch/mips/kernel/ptrace.c
> +++ b/arch/mips/kernel/ptrace.c
> @@ -409,23 +409,28 @@ static int fpr_get(struct task_struct *target,
>  	int err;
>  	u64 fpr_val;
>  
> -	/* XXX fcr31  */
> -
> -	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
> -		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
> -					   &target->thread.fpu,
> -					   0, sizeof(elf_fpregset_t));
> -
> -	for (i = 0; i < NUM_FPU_REGS; i++) {
> -		fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
> +	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
>  		err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
> -					  &fpr_val, i * sizeof(elf_fpreg_t),
> -					  (i + 1) * sizeof(elf_fpreg_t));
> +					  &target->thread.fpu.fpr,
> +					  0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
>  		if (err)
>  			return err;
> +	} else {
> +		for (i = 0; i < NUM_FPU_REGS; i++) {
> +			fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
> +			err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
> +						  &fpr_val,
> +						  i * sizeof(elf_fpreg_t),
> +						  (i + 1) * sizeof(elf_fpreg_t));
> +			if (err)
> +				return err;
> +		}
>  	}
>  
> -	return 0;
> +	return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
> +			    &target->thread.fpu.fcr31,
> +			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
> +			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));

The only problem I can think of is that the final register in the regset
will still be treated as 64b (regset->size) as far as ptrace is
concerned, so I'm not sure how best to handle this. I presume the pre
regset core dump format placed the 32b FCSR value immediately after
the 64b $f31, as you have here? In which case we should probably at
least zero out the other 4 bytes of this final "register", assuming
the extra 4 bytes compared to the pre-regset version isn't a problem?

Thanks,
    Paul

>  }
>  
>  static int fpr_set(struct task_struct *target,
> @@ -436,23 +441,33 @@ static int fpr_set(struct task_struct *target,
>  	unsigned i;
>  	int err;
>  	u64 fpr_val;
> +	u32 fcr31;
>  
> -	/* XXX fcr31  */
> -
> -	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
> -		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
> -					  &target->thread.fpu,
> -					  0, sizeof(elf_fpregset_t));
> -
> -	for (i = 0; i < NUM_FPU_REGS; i++) {
> +	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
>  		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
> -					 &fpr_val, i * sizeof(elf_fpreg_t),
> -					 (i + 1) * sizeof(elf_fpreg_t));
> +					 &target->thread.fpu.fpr,
> +					 0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
>  		if (err)
>  			return err;
> -		set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
> +	} else {
> +		for (i = 0; i < NUM_FPU_REGS; i++) {
> +			err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
> +						 &fpr_val,
> +						 i * sizeof(elf_fpreg_t),
> +						 (i + 1) * sizeof(elf_fpreg_t));
> +			if (err)
> +				return err;
> +			set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
> +		}
>  	}
>  
> +	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31,
> +			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
> +			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
> +	if (err)
> +		return err;
> +
> +	target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;
>  	return 0;
>  }
>  
> -- 
> 1.9.1
> 

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

* Re: [PATCH 05/11] MIPS: ptrace: Always copy FCSR in FP regset
  2014-07-23 14:12     ` Paul Burton
  (?)
@ 2014-07-23 16:20     ` Alex Smith
  -1 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-23 16:20 UTC (permalink / raw)
  To: Paul Burton; +Cc: linux-mips, stable

On 23 July 2014 15:12, Paul Burton <paul.burton@imgtec.com> wrote:
> On Wed, Jul 23, 2014 at 02:40:10PM +0100, Alex Smith wrote:
>> Copy FCSR in the FP regset to match the original pre-regset core dumper.
>> The code paths for where sizeof(union fpureg) == sizeof(elf_fpreg_t)
>> already do so, but they actually copy 4 bytes more than they should do
>> as FCSR is only 32 bits. The not equal code paths do not copy it at all.
>> Therefore change the copy to be done explicitly (with the correct size)
>> for both paths.
>
> Ah, I hadn't realised that ELF_NFPREG == 33, sneaky! That together with
> the "XXX fcr31" comment led me to believe the FP regset didn't include
> FCSR which is why I hadn't fixed the oops there or taken it into account
> for the case where FPR size != sizeof(elf_fpreg_t) (ie. when MSA support
> is enabled).
>
>> Additionally, clear the cause bits from FCSR when setting the FP regset
>> to avoid the possibility of causing an FP exception (and an oops) in the
>> kernel.
>>
>> Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
>> Cc: Paul Burton <paul.burton@imgtec.com>
>> Cc: <stable@vger.kernel.org> # v3.13+
>> ---
>> This patch incorporates a fix for another instance of the bug fixed by
>> Paul Burton's patch "MIPS: prevent user from setting FCSR cause bits" -
>> the code path in fpr_set for sizeof(fpureg) == sizeof(elf_fpreg_t)
>> copied fcr31 without clearing cause bits. I've incorporated a fix for
>> it into this patch to so that it's easier to apply both patches without
>> conflicts.
>> ---
>>  arch/mips/kernel/ptrace.c | 61 +++++++++++++++++++++++++++++------------------
>>  1 file changed, 38 insertions(+), 23 deletions(-)
>>
>> diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
>> index 8bd13ed..ffc2e37 100644
>> --- a/arch/mips/kernel/ptrace.c
>> +++ b/arch/mips/kernel/ptrace.c
>> @@ -409,23 +409,28 @@ static int fpr_get(struct task_struct *target,
>>       int err;
>>       u64 fpr_val;
>>
>> -     /* XXX fcr31  */
>> -
>> -     if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
>> -             return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
>> -                                        &target->thread.fpu,
>> -                                        0, sizeof(elf_fpregset_t));
>> -
>> -     for (i = 0; i < NUM_FPU_REGS; i++) {
>> -             fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
>> +     if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
>>               err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
>> -                                       &fpr_val, i * sizeof(elf_fpreg_t),
>> -                                       (i + 1) * sizeof(elf_fpreg_t));
>> +                                       &target->thread.fpu.fpr,
>> +                                       0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
>>               if (err)
>>                       return err;
>> +     } else {
>> +             for (i = 0; i < NUM_FPU_REGS; i++) {
>> +                     fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
>> +                     err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
>> +                                               &fpr_val,
>> +                                               i * sizeof(elf_fpreg_t),
>> +                                               (i + 1) * sizeof(elf_fpreg_t));
>> +                     if (err)
>> +                             return err;
>> +             }
>>       }
>>
>> -     return 0;
>> +     return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
>> +                         &target->thread.fpu.fcr31,
>> +                         NUM_FPU_REGS * sizeof(elf_fpreg_t),
>> +                         (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
>
> The only problem I can think of is that the final register in the regset
> will still be treated as 64b (regset->size) as far as ptrace is
> concerned, so I'm not sure how best to handle this. I presume the pre
> regset core dump format placed the 32b FCSR value immediately after
> the 64b $f31, as you have here? In which case we should probably at
> least zero out the other 4 bytes of this final "register", assuming
> the extra 4 bytes compared to the pre-regset version isn't a problem?

Yes, this should now exactly match the old core dump code, which
copies the 32-bit FCSR immediately after f31 (see dump_task_fpu). The
last 4 bytes were still there with the old code, but it never actually
touched them. You're right that this should zero it out. I'll do a v2
with that fixed.

Thanks,
Alex

>
> Thanks,
>     Paul
>
>>  }
>>
>>  static int fpr_set(struct task_struct *target,
>> @@ -436,23 +441,33 @@ static int fpr_set(struct task_struct *target,
>>       unsigned i;
>>       int err;
>>       u64 fpr_val;
>> +     u32 fcr31;
>>
>> -     /* XXX fcr31  */
>> -
>> -     if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
>> -             return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
>> -                                       &target->thread.fpu,
>> -                                       0, sizeof(elf_fpregset_t));
>> -
>> -     for (i = 0; i < NUM_FPU_REGS; i++) {
>> +     if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
>>               err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
>> -                                      &fpr_val, i * sizeof(elf_fpreg_t),
>> -                                      (i + 1) * sizeof(elf_fpreg_t));
>> +                                      &target->thread.fpu.fpr,
>> +                                      0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
>>               if (err)
>>                       return err;
>> -             set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
>> +     } else {
>> +             for (i = 0; i < NUM_FPU_REGS; i++) {
>> +                     err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
>> +                                              &fpr_val,
>> +                                              i * sizeof(elf_fpreg_t),
>> +                                              (i + 1) * sizeof(elf_fpreg_t));
>> +                     if (err)
>> +                             return err;
>> +                     set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
>> +             }
>>       }
>>
>> +     err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31,
>> +                         NUM_FPU_REGS * sizeof(elf_fpreg_t),
>> +                         (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
>> +     if (err)
>> +             return err;
>> +
>> +     target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;
>>       return 0;
>>  }
>>
>> --
>> 1.9.1
>>

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

* [PATCH v2 05/11] MIPS: ptrace: Always copy FCSR in FP regset
@ 2014-07-24 12:50     ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-24 12:50 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, Paul Burton, stable

Copy FCSR in the FP regset to match the original pre-regset core dumper.
The code paths for where sizeof(union fpureg) == sizeof(elf_fpreg_t)
already do so, but they actually copy 4 bytes more than they should do
as FCSR is only 32 bits. The not equal code paths do not copy it at all.
Therefore change the copy to be done explicitly (with the correct size)
for both paths.

Additionally, clear the cause bits from FCSR when setting the FP regset
to avoid the possibility of causing an FP exception (and an oops) in the
kernel.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: <stable@vger.kernel.org> # v3.13+
---
Changes in v2:
 - Zero fill the last 4 bytes in the FP regset.
---
 arch/mips/kernel/ptrace.c | 73 +++++++++++++++++++++++++++++++----------------
 1 file changed, 49 insertions(+), 24 deletions(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 8bd13ed..e082079 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -409,23 +409,35 @@ static int fpr_get(struct task_struct *target,
 	int err;
 	u64 fpr_val;
 
-	/* XXX fcr31  */
-
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					   &target->thread.fpu,
-					   0, sizeof(elf_fpregset_t));
-
-	for (i = 0; i < NUM_FPU_REGS; i++) {
-		fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
 		err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					  &fpr_val, i * sizeof(elf_fpreg_t),
-					  (i + 1) * sizeof(elf_fpreg_t));
+					  &target->thread.fpu.fpr,
+					  0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 		if (err)
 			return err;
+	} else {
+		for (i = 0; i < NUM_FPU_REGS; i++) {
+			fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+			err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+						  &fpr_val,
+						  i * sizeof(elf_fpreg_t),
+						  (i + 1) * sizeof(elf_fpreg_t));
+			if (err)
+				return err;
+		}
 	}
 
-	return 0;
+	err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			   &target->thread.fpu.fcr31,
+			   NUM_FPU_REGS * sizeof(elf_fpreg_t),
+			   (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
+	if (err)
+		return err;
+
+	/* Zero fill the remaining 4 bytes. */
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32),
+			    sizeof(elf_fpregset_t));
 }
 
 static int fpr_set(struct task_struct *target,
@@ -436,24 +448,37 @@ static int fpr_set(struct task_struct *target,
 	unsigned i;
 	int err;
 	u64 fpr_val;
+	u32 fcr31;
 
-	/* XXX fcr31  */
-
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					  &target->thread.fpu,
-					  0, sizeof(elf_fpregset_t));
-
-	for (i = 0; i < NUM_FPU_REGS; i++) {
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
 		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					 &fpr_val, i * sizeof(elf_fpreg_t),
-					 (i + 1) * sizeof(elf_fpreg_t));
+					 &target->thread.fpu.fpr,
+					 0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 		if (err)
 			return err;
-		set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+	} else {
+		for (i = 0; i < NUM_FPU_REGS; i++) {
+			err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						 &fpr_val,
+						 i * sizeof(elf_fpreg_t),
+						 (i + 1) * sizeof(elf_fpreg_t));
+			if (err)
+				return err;
+			set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+		}
 	}
 
-	return 0;
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31,
+			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
+	if (err)
+		return err;
+
+	target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;
+
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32),
+			    sizeof(elf_fpregset_t));
 }
 
 enum mips_regset {
-- 
1.9.1

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

* [PATCH v2 05/11] MIPS: ptrace: Always copy FCSR in FP regset
@ 2014-07-24 12:50     ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-07-24 12:50 UTC (permalink / raw)
  To: linux-mips; +Cc: Alex Smith, Paul Burton, stable

Copy FCSR in the FP regset to match the original pre-regset core dumper.
The code paths for where sizeof(union fpureg) == sizeof(elf_fpreg_t)
already do so, but they actually copy 4 bytes more than they should do
as FCSR is only 32 bits. The not equal code paths do not copy it at all.
Therefore change the copy to be done explicitly (with the correct size)
for both paths.

Additionally, clear the cause bits from FCSR when setting the FP regset
to avoid the possibility of causing an FP exception (and an oops) in the
kernel.

Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: <stable@vger.kernel.org> # v3.13+
---
Changes in v2:
 - Zero fill the last 4 bytes in the FP regset.
---
 arch/mips/kernel/ptrace.c | 73 +++++++++++++++++++++++++++++++----------------
 1 file changed, 49 insertions(+), 24 deletions(-)

diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 8bd13ed..e082079 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -409,23 +409,35 @@ static int fpr_get(struct task_struct *target,
 	int err;
 	u64 fpr_val;
 
-	/* XXX fcr31  */
-
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					   &target->thread.fpu,
-					   0, sizeof(elf_fpregset_t));
-
-	for (i = 0; i < NUM_FPU_REGS; i++) {
-		fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
 		err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
-					  &fpr_val, i * sizeof(elf_fpreg_t),
-					  (i + 1) * sizeof(elf_fpreg_t));
+					  &target->thread.fpu.fpr,
+					  0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 		if (err)
 			return err;
+	} else {
+		for (i = 0; i < NUM_FPU_REGS; i++) {
+			fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
+			err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+						  &fpr_val,
+						  i * sizeof(elf_fpreg_t),
+						  (i + 1) * sizeof(elf_fpreg_t));
+			if (err)
+				return err;
+		}
 	}
 
-	return 0;
+	err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+			   &target->thread.fpu.fcr31,
+			   NUM_FPU_REGS * sizeof(elf_fpreg_t),
+			   (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
+	if (err)
+		return err;
+
+	/* Zero fill the remaining 4 bytes. */
+	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32),
+			    sizeof(elf_fpregset_t));
 }
 
 static int fpr_set(struct task_struct *target,
@@ -436,24 +448,37 @@ static int fpr_set(struct task_struct *target,
 	unsigned i;
 	int err;
 	u64 fpr_val;
+	u32 fcr31;
 
-	/* XXX fcr31  */
-
-	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
-		return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					  &target->thread.fpu,
-					  0, sizeof(elf_fpregset_t));
-
-	for (i = 0; i < NUM_FPU_REGS; i++) {
+	if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
 		err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
-					 &fpr_val, i * sizeof(elf_fpreg_t),
-					 (i + 1) * sizeof(elf_fpreg_t));
+					 &target->thread.fpu.fpr,
+					 0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
 		if (err)
 			return err;
-		set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+	} else {
+		for (i = 0; i < NUM_FPU_REGS; i++) {
+			err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+						 &fpr_val,
+						 i * sizeof(elf_fpreg_t),
+						 (i + 1) * sizeof(elf_fpreg_t));
+			if (err)
+				return err;
+			set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
+		}
 	}
 
-	return 0;
+	err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31,
+			    NUM_FPU_REGS * sizeof(elf_fpreg_t),
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
+	if (err)
+		return err;
+
+	target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;
+
+	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+			    (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32),
+			    sizeof(elf_fpregset_t));
 }
 
 enum mips_regset {
-- 
1.9.1

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

* Re: [PATCH v2 06/11] MIPS: O32/32-bit: Fix bug which can cause incorrect system call restarts
  2014-07-23 13:40   ` Alex Smith
  (?)
@ 2014-07-30  9:31   ` Aurelien Jarno
  -1 siblings, 0 replies; 25+ messages in thread
From: Aurelien Jarno @ 2014-07-30  9:31 UTC (permalink / raw)
  To: Alex Smith; +Cc: linux-mips, Alex Smith, stable, Ralf Baechle

On Wed, Jul 23, 2014 at 02:40:11PM +0100, Alex Smith wrote:
> From: Alex Smith <alex.smith@imgtec.com>
> 
> On 32-bit/O32, pt_regs has a padding area at the beginning into which the
> syscall arguments passed via the user stack are copied. 4 arguments
> totalling 16 bytes are copied to offset 16 bytes into this area, however
> the area is only 24 bytes long. This means the last 2 arguments overwrite
> pt_regs->regs[{0,1}].
> 
> If a syscall function returns an error, handle_sys stores the original
> syscall number in pt_regs->regs[0] for syscall restart. signal.c checks
> whether regs[0] is non-zero, if it is it will check whether the syscall
> return value is one of the ERESTART* codes to see if it must be
> restarted.
> 
> Should a syscall be made that results in a non-zero value being copied
> off the user stack into regs[0], and then returns a positive (non-error)
> value that matches one of the ERESTART* error codes, this can be mistaken
> for requiring a syscall restart.
> 
> While the possibility for this to occur has always existed, it is made
> much more likely to occur by commit 46e12c07b3b9 ("MIPS: O32 / 32-bit:
> Always copy 4 stack arguments."), since now every syscall will copy 4
> arguments and overwrite regs[0], rather than just those with 7 or 8
> arguments.
> 
> Since that commit, booting Debian under a 32-bit MIPS kernel almost
> always results in a hang early in boot, due to a wait4 syscall returning
> a PID that matches one of the ERESTART* codes, which then causes an
> incorrect restart of the syscall.
> 
> The problem is fixed by increasing the size of the padding area so that
> arguments copied off the stack will not overwrite pt_regs->regs[{0,1}].
> 
> Signed-off-by: Alex Smith <alex.smith@imgtec.com>
> Cc: <stable@vger.kernel.org> # v3.13+
> ---
> Changes in v2:
>  - Rebase on current upstream.
>  - Split comment change into a separate commit.
> 
> I've rebased this patch on top of current mips-for-linux-next. However,
> for it to be applied to stable it needs an additional change to the
> PT_PADSLOT* definitions in arch/mips/kernel/smtc-asm.S to account for
> the changed pt_regs offsets. This file no longer exists since SMTC has
> been dropped.
> 
> I'm not sure what the correct way to deal with this is - can an
> alternate version of the patch be submitted for stable?
> ---
>  arch/mips/include/asm/ptrace.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
> index 7e6e682..c301fa9 100644
> --- a/arch/mips/include/asm/ptrace.h
> +++ b/arch/mips/include/asm/ptrace.h
> @@ -23,7 +23,7 @@
>  struct pt_regs {
>  #ifdef CONFIG_32BIT
>  	/* Pad bytes for argument save space on the stack. */
> -	unsigned long pad0[6];
> +	unsigned long pad0[8];
>  #endif
>  
>  	/* Saved main processor registers. */

This patch looks fine to me, and I confirm it fixes a problem. Without
this patch, I am not able to boot a Debian user land on a 32-bit system.
It's a regression, so I think it should be merged as soon as possible,
even if the other patches in this series are merged later.

Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
Tested-by: Aurelien Jarno <aurelien@aurel32.net>

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [PATCH v2 05/11] MIPS: ptrace: Always copy FCSR in FP regset
       [not found]     ` <53F4ABA2.3030008@imgtec.com>
@ 2014-08-20 15:15       ` Alex Smith
  0 siblings, 0 replies; 25+ messages in thread
From: Alex Smith @ 2014-08-20 15:15 UTC (permalink / raw)
  To: James Hogan, Ralf; +Cc: linux-mips, Paul Burton, stable

Hi James,

On 20 August 2014 15:07, James Hogan <james.hogan@imgtec.com> wrote:
> Hi Ralf,
>
> On 24/07/14 13:50, Alex Smith wrote:
>> Copy FCSR in the FP regset to match the original pre-regset core dumper.
>> The code paths for where sizeof(union fpureg) == sizeof(elf_fpreg_t)
>> already do so, but they actually copy 4 bytes more than they should do
>> as FCSR is only 32 bits. The not equal code paths do not copy it at all.
>> Therefore change the copy to be done explicitly (with the correct size)
>> for both paths.
>>
>> Additionally, clear the cause bits from FCSR when setting the FP regset
>> to avoid the possibility of causing an FP exception (and an oops) in the
>> kernel.
>>
>> Signed-off-by: Alex Smith <alex@alex-smith.me.uk>
>> Cc: Paul Burton <paul.burton@imgtec.com>
>> Cc: <stable@vger.kernel.org> # v3.13+
>
> This patch seems to have been missed, although all the others in the
> series were included in the main v3.17 merge. Was that intentional?

Ralf emailed me saying he'd dropped the patch because it was causing
warnings, and he didn't respond when I asked what the warnings were
(I'm unable to reproduce any).

Ralf: if you can let me know what warnings you were getting I can send
an updated patch.

Thanks,
Alex

>
> Cheers
> James
>
>> ---
>> Changes in v2:
>>  - Zero fill the last 4 bytes in the FP regset.
>> ---
>>  arch/mips/kernel/ptrace.c | 73 +++++++++++++++++++++++++++++++----------------
>>  1 file changed, 49 insertions(+), 24 deletions(-)
>>
>> diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
>> index 8bd13ed..e082079 100644
>> --- a/arch/mips/kernel/ptrace.c
>> +++ b/arch/mips/kernel/ptrace.c
>> @@ -409,23 +409,35 @@ static int fpr_get(struct task_struct *target,
>>       int err;
>>       u64 fpr_val;
>>
>> -     /* XXX fcr31  */
>> -
>> -     if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
>> -             return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
>> -                                        &target->thread.fpu,
>> -                                        0, sizeof(elf_fpregset_t));
>> -
>> -     for (i = 0; i < NUM_FPU_REGS; i++) {
>> -             fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
>> +     if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
>>               err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
>> -                                       &fpr_val, i * sizeof(elf_fpreg_t),
>> -                                       (i + 1) * sizeof(elf_fpreg_t));
>> +                                       &target->thread.fpu.fpr,
>> +                                       0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
>>               if (err)
>>                       return err;
>> +     } else {
>> +             for (i = 0; i < NUM_FPU_REGS; i++) {
>> +                     fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
>> +                     err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
>> +                                               &fpr_val,
>> +                                               i * sizeof(elf_fpreg_t),
>> +                                               (i + 1) * sizeof(elf_fpreg_t));
>> +                     if (err)
>> +                             return err;
>> +             }
>>       }
>>
>> -     return 0;
>> +     err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
>> +                        &target->thread.fpu.fcr31,
>> +                        NUM_FPU_REGS * sizeof(elf_fpreg_t),
>> +                        (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
>> +     if (err)
>> +             return err;
>> +
>> +     /* Zero fill the remaining 4 bytes. */
>> +     return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
>> +                         (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32),
>> +                         sizeof(elf_fpregset_t));
>>  }
>>
>>  static int fpr_set(struct task_struct *target,
>> @@ -436,24 +448,37 @@ static int fpr_set(struct task_struct *target,
>>       unsigned i;
>>       int err;
>>       u64 fpr_val;
>> +     u32 fcr31;
>>
>> -     /* XXX fcr31  */
>> -
>> -     if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t))
>> -             return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
>> -                                       &target->thread.fpu,
>> -                                       0, sizeof(elf_fpregset_t));
>> -
>> -     for (i = 0; i < NUM_FPU_REGS; i++) {
>> +     if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) {
>>               err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
>> -                                      &fpr_val, i * sizeof(elf_fpreg_t),
>> -                                      (i + 1) * sizeof(elf_fpreg_t));
>> +                                      &target->thread.fpu.fpr,
>> +                                      0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
>>               if (err)
>>                       return err;
>> -             set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
>> +     } else {
>> +             for (i = 0; i < NUM_FPU_REGS; i++) {
>> +                     err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
>> +                                              &fpr_val,
>> +                                              i * sizeof(elf_fpreg_t),
>> +                                              (i + 1) * sizeof(elf_fpreg_t));
>> +                     if (err)
>> +                             return err;
>> +                     set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
>> +             }
>>       }
>>
>> -     return 0;
>> +     err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31,
>> +                         NUM_FPU_REGS * sizeof(elf_fpreg_t),
>> +                         (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32));
>> +     if (err)
>> +             return err;
>> +
>> +     target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X;
>> +
>> +     return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
>> +                         (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32),
>> +                         sizeof(elf_fpregset_t));
>>  }
>>
>>  enum mips_regset {
>>

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

end of thread, other threads:[~2014-08-22 21:36 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-23 13:40 [PATCH 00/11] MIPS ptrace/core dump fixes and cleanups Alex Smith
2014-07-23 13:40 ` [PATCH 01/11] MIPS: ptrace: Avoid smp_processor_id() when retrieving FPU IR Alex Smith
2014-07-23 13:40   ` Alex Smith
2014-07-23 13:40 ` [PATCH 02/11] MIPS: ptrace: Test correct task's flags in task_user_regset_view() Alex Smith
2014-07-23 13:40   ` Alex Smith
2014-07-23 13:40 ` [PATCH 03/11] MIPS: asm/reg.h: Make 32- and 64-bit definitions available at the same time Alex Smith
2014-07-23 13:40   ` Alex Smith
2014-07-23 13:40 ` [PATCH 04/11] MIPS: ptrace: Change GP regset to use correct core dump register layout Alex Smith
2014-07-23 13:40   ` Alex Smith
2014-07-23 13:40 ` [PATCH 05/11] MIPS: ptrace: Always copy FCSR in FP regset Alex Smith
2014-07-23 13:40   ` Alex Smith
2014-07-23 14:12   ` Paul Burton
2014-07-23 14:12     ` Paul Burton
2014-07-23 16:20     ` Alex Smith
2014-07-24 12:50   ` [PATCH v2 " Alex Smith
2014-07-24 12:50     ` Alex Smith
     [not found]     ` <53F4ABA2.3030008@imgtec.com>
2014-08-20 15:15       ` Alex Smith
2014-07-23 13:40 ` [PATCH v2 06/11] MIPS: O32/32-bit: Fix bug which can cause incorrect system call restarts Alex Smith
2014-07-23 13:40   ` Alex Smith
2014-07-30  9:31   ` Aurelien Jarno
2014-07-23 13:40 ` [PATCH 07/11] MIPS: O32/32-bit: Remove outdated comment Alex Smith
2014-07-23 13:40 ` [PATCH 08/11] MIPS: ptrace: Fix user pt_regs definition, use in ptrace_{get,set}regs() Alex Smith
2014-07-23 13:40 ` [PATCH 09/11] MIPS: Remove old core dump functions Alex Smith
2014-07-23 13:40 ` [PATCH 10/11] MIPS: Remove asm/user.h Alex Smith
2014-07-23 13:40 ` [PATCH 11/11] MIPS: asm/reg.h: Move to uapi Alex Smith

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.