powerpc/ptrace: Fix coredump since ptrace TM changes
Commit8d460f6156
("powerpc/process: Add the function flush_tmregs_to_thread") added flush_tmregs_to_thread() and included the assumption that it would only be called for a task which is not current. Although this is correct for ptrace, when generating a core dump, some of the routines which call flush_tmregs_to_thread() are called. This leads to a WARNing such as: Not expecting ptrace on self: TM regs may be incorrect ------------[ cut here ]------------ WARNING: CPU: 123 PID: 7727 at arch/powerpc/kernel/process.c:1088 flush_tmregs_to_thread+0x78/0x80 CPU: 123 PID: 7727 Comm: libvirtd Not tainted 4.8.0-rc1-gcc6x-g61e8a0d #1 task: c000000fe631b600 task.stack: c000000fe63b0000 NIP: c00000000001a1a8 LR: c00000000001a1a4 CTR: c000000000717780 REGS: c000000fe63b3420 TRAP: 0700 Not tainted (4.8.0-rc1-gcc6x-g61e8a0d) MSR: 900000010282b033 <SF,HV,VEC,VSX,EE,FP,ME,IR,DR,RI,LE,TM[E]> CR: 28004222 XER: 20000000 ... NIP [c00000000001a1a8] flush_tmregs_to_thread+0x78/0x80 LR [c00000000001a1a4] flush_tmregs_to_thread+0x74/0x80 Call Trace: flush_tmregs_to_thread+0x74/0x80 (unreliable) vsr_get+0x64/0x1a0 elf_core_dump+0x604/0x1430 do_coredump+0x5fc/0x1200 get_signal+0x398/0x740 do_signal+0x54/0x2b0 do_notify_resume+0x98/0xb0 ret_from_except_lite+0x70/0x74 So fix flush_tmregs_to_thread() to detect the case where it is called on current, and a transaction is active, and in that case flush the TM regs to the thread_struct. This patch also moves flush_tmregs_to_thread() into ptrace.c as it is only called from that file. Fixes:8d460f6156
("powerpc/process: Add the function flush_tmregs_to_thread") Signed-off-by: Cyril Bur <cyrilbur@gmail.com> [mpe: Flesh out change log] Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
Родитель
1bc8b816cb
Коммит
c7a318ba86
|
@ -75,14 +75,6 @@ static inline void disable_kernel_spe(void)
|
||||||
static inline void __giveup_spe(struct task_struct *t) { }
|
static inline void __giveup_spe(struct task_struct *t) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
||||||
extern void flush_tmregs_to_thread(struct task_struct *);
|
|
||||||
#else
|
|
||||||
static inline void flush_tmregs_to_thread(struct task_struct *t)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline void clear_task_ebb(struct task_struct *t)
|
static inline void clear_task_ebb(struct task_struct *t)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PPC_BOOK3S_64
|
#ifdef CONFIG_PPC_BOOK3S_64
|
||||||
|
|
|
@ -1074,26 +1074,6 @@ static inline void restore_sprs(struct thread_struct *old_thread,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
|
||||||
void flush_tmregs_to_thread(struct task_struct *tsk)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Process self tracing is not yet supported through
|
|
||||||
* ptrace interface. Ptrace generic code should have
|
|
||||||
* prevented this from happening in the first place.
|
|
||||||
* Warn once here with the message, if some how it
|
|
||||||
* is attempted.
|
|
||||||
*/
|
|
||||||
WARN_ONCE(tsk == current,
|
|
||||||
"Not expecting ptrace on self: TM regs may be incorrect\n");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If task is not current, it should have been flushed
|
|
||||||
* already to it's thread_struct during __switch_to().
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct task_struct *__switch_to(struct task_struct *prev,
|
struct task_struct *__switch_to(struct task_struct *prev,
|
||||||
struct task_struct *new)
|
struct task_struct *new)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/switch_to.h>
|
#include <asm/switch_to.h>
|
||||||
|
#include <asm/tm.h>
|
||||||
|
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include <trace/events/syscalls.h>
|
#include <trace/events/syscalls.h>
|
||||||
|
@ -118,6 +119,24 @@ static const struct pt_regs_offset regoffset_table[] = {
|
||||||
REG_OFFSET_END,
|
REG_OFFSET_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||||
|
static void flush_tmregs_to_thread(struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If task is not current, it will have been flushed already to
|
||||||
|
* it's thread_struct during __switch_to().
|
||||||
|
*
|
||||||
|
* A reclaim flushes ALL the state.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (tsk == current && MSR_TM_SUSPENDED(mfmsr()))
|
||||||
|
tm_reclaim_current(TM_CAUSE_SIGNAL);
|
||||||
|
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void flush_tmregs_to_thread(struct task_struct *tsk) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* regs_query_register_offset() - query register offset from its name
|
* regs_query_register_offset() - query register offset from its name
|
||||||
* @name: the name of a register
|
* @name: the name of a register
|
||||||
|
|
Загрузка…
Ссылка в новой задаче