mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-30 22:03:17 +01:00
Add a user_regset_view for Alpha and switch ELF core dumping to CORE_DUMP_USE_REGSET. General-purpose registers are exported in ELF gregs layout, including callee-saved registers and a correct user stack pointer. The user stack pointer is not preserved in pt_regs on Alpha, so expose it from the PCB, or via rdusp() for the current task, when building the ELF register image. This makes the user stack pointer consistent for core dumps, ptrace regsets, and PTRACE_GET_SYSCALL_INFO. Implement regset get/set callbacks for both NT_PRSTATUS and NT_PRFPREG. The callbacks translate between Alpha's pt_regs/thread state and the ELF-visible register layouts, while the common ptrace regset code handles PTRACE_GETREGSET and PTRACE_SETREGSET iovec semantics. This avoids duplicating subtle short-buffer and oversized-buffer behavior in arch_ptrace(). With these changes Alpha satisfies the requirements for HAVE_ARCH_TRACEHOOK and selects it, enabling generic tracehook and ptrace syscall-info code paths without changing the existing syscall entry ABI. Reviewed-by: Matt Turner <[email protected]> Tested-by: Matt Turner <[email protected]> Signed-off-by: Magnus Lindholm <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Magnus Lindholm <[email protected]>
144 lines
4.6 KiB
C
144 lines
4.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ALPHA_THREAD_INFO_H
|
|
#define _ALPHA_THREAD_INFO_H
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#ifndef __ASSEMBLER__
|
|
#include <asm/processor.h>
|
|
#include <asm/types.h>
|
|
#include <asm/hwrpb.h>
|
|
#include <asm/sysinfo.h>
|
|
#endif
|
|
|
|
#ifndef __ASSEMBLER__
|
|
struct thread_info {
|
|
struct pcb_struct pcb; /* palcode state */
|
|
|
|
struct task_struct *task; /* main task structure */
|
|
unsigned int flags; /* low level flags */
|
|
unsigned int ieee_state; /* see fpu.h */
|
|
|
|
unsigned cpu; /* current CPU */
|
|
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
|
unsigned int status; /* thread-synchronous flags */
|
|
|
|
int bpt_nsaved;
|
|
unsigned long bpt_addr[2]; /* breakpoint handling */
|
|
unsigned int bpt_insn[2];
|
|
unsigned long fp[32];
|
|
};
|
|
|
|
/*
|
|
* Macros/functions for gaining access to the thread information structure.
|
|
*/
|
|
#define INIT_THREAD_INFO(tsk) \
|
|
{ \
|
|
.task = &tsk, \
|
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
|
}
|
|
|
|
/* How to get the thread information struct from C. */
|
|
register struct thread_info *__current_thread_info __asm__("$8");
|
|
#define current_thread_info() __current_thread_info
|
|
|
|
register unsigned long *current_stack_pointer __asm__ ("$30");
|
|
|
|
#endif /* __ASSEMBLER__ */
|
|
|
|
/* Thread information allocation. */
|
|
#define THREAD_SIZE_ORDER 1
|
|
#define THREAD_SIZE (2*PAGE_SIZE)
|
|
|
|
/*
|
|
* Thread information flags:
|
|
* - these are process state flags and used from assembly
|
|
* - pending work-to-be-done flags come first and must be assigned to be
|
|
* within bits 0 to 7 to fit in and immediate operand.
|
|
*
|
|
* (Historically TIF_SYSCALL_TRACE was known to be 0 via blbs, but we may
|
|
* also test multiple bits via masks now.)
|
|
*/
|
|
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
|
|
#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
|
|
#define TIF_SIGPENDING 2 /* signal pending */
|
|
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
|
|
#define TIF_SYSCALL_AUDIT 4 /* syscall audit active */
|
|
#define TIF_NOTIFY_SIGNAL 5 /* signal notifications exist */
|
|
#define TIF_SECCOMP 6 /* seccomp syscall filtering active */
|
|
#define TIF_SYSCALL_TRACEPOINT 7 /* syscall tracepoint instrumentation */
|
|
#define TIF_DIE_IF_KERNEL 9 /* dik recursion lock */
|
|
#define TIF_MEMDIE 13 /* is terminating due to OOM killer */
|
|
#define TIF_POLLING_NRFLAG 14 /* idle is polling for TIF_NEED_RESCHED */
|
|
|
|
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
|
|
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
|
|
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
|
|
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
|
|
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
|
|
#define _TIF_NOTIFY_SIGNAL (1<<TIF_NOTIFY_SIGNAL)
|
|
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
|
|
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
|
|
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
|
|
|
|
/*
|
|
* Work to do on syscall entry (in entry.S).
|
|
* If you want this to exactly mirror what entry.S checks, keep it aligned
|
|
* with the mask used before branching to syscall_trace_enter().
|
|
*/
|
|
#ifdef CONFIG_AUDITSYSCALL
|
|
# define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP \
|
|
| _TIF_SYSCALL_TRACEPOINT)
|
|
#else
|
|
# define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)
|
|
#endif
|
|
|
|
/* Work to do on interrupt/exception return. */
|
|
#define _TIF_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
|
|
_TIF_NOTIFY_RESUME | _TIF_NOTIFY_SIGNAL)
|
|
|
|
#define TS_UAC_NOPRINT 0x0001 /* ! Preserve the following three */
|
|
#define TS_UAC_NOFIX 0x0002 /* ! flags as they match */
|
|
#define TS_UAC_SIGBUS 0x0004 /* ! userspace part of 'osf_sysinfo' */
|
|
|
|
#define TS_SAVED_FP 0x0008
|
|
#define TS_RESTORE_FP 0x0010
|
|
|
|
#define SET_UNALIGN_CTL(task,value) ({ \
|
|
__u32 status = task_thread_info(task)->status & ~UAC_BITMASK; \
|
|
if (value & PR_UNALIGN_NOPRINT) \
|
|
status |= TS_UAC_NOPRINT; \
|
|
if (value & PR_UNALIGN_SIGBUS) \
|
|
status |= TS_UAC_SIGBUS; \
|
|
if (value & 4) /* alpha-specific */ \
|
|
status |= TS_UAC_NOFIX; \
|
|
task_thread_info(task)->status = status; \
|
|
0; })
|
|
|
|
#define GET_UNALIGN_CTL(task,value) ({ \
|
|
__u32 status = task_thread_info(task)->status & ~UAC_BITMASK; \
|
|
__u32 res = 0; \
|
|
if (status & TS_UAC_NOPRINT) \
|
|
res |= PR_UNALIGN_NOPRINT; \
|
|
if (status & TS_UAC_SIGBUS) \
|
|
res |= PR_UNALIGN_SIGBUS; \
|
|
if (status & TS_UAC_NOFIX) \
|
|
res |= 4; \
|
|
put_user(res, (int __user *)(value)); \
|
|
})
|
|
|
|
#ifndef __ASSEMBLER__
|
|
extern void __save_fpu(void);
|
|
|
|
static inline void save_fpu(void)
|
|
{
|
|
if (!(current_thread_info()->status & TS_SAVED_FP)) {
|
|
current_thread_info()->status |= TS_SAVED_FP;
|
|
__save_fpu();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#endif /* __KERNEL__ */
|
|
#endif /* _ALPHA_THREAD_INFO_H */
|