* [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], ¤t->thread.fpu.fpr[i], sizeof(*r));
-
- memcpy(&r[NUM_FPU_REGS], ¤t->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.