diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h
index 758ae984ff97..465cc9713895 100644
--- a/arch/arm64/include/uapi/asm/ptrace.h
+++ b/arch/arm64/include/uapi/asm/ptrace.h
@@ -109,6 +109,10 @@ struct user_hwdebug_state {
} dbg_regs[16];
};
+#define PTRACE_O_ARM64_RAW_REGS (1 << 28)
+
+#define _PTRACE_O_ARCH_OPTIONS PTRACE_O_ARM64_RAW_REGS
+
/* SVE/FP/SIMD state (NT_ARM_SVE) */
struct user_sve_header {diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 39da03104528..591a4478ad76 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -565,21 +565,23 @@ static int gpr_get(struct task_struct *target,
unsigned long saved_reg;
int ret;
- /*
- * We have some ABI weirdness here in the way that we handle syscall
- * exit stops because we indicate whether or not the stop has been
- * signalled from syscall entry or syscall exit by clobbering the general
- * purpose register x7.
- */
saved_reg = uregs->regs[7];
- switch (target->ptrace_message) {
- case PTRACE_EVENTMSG_SYSCALL_ENTRY:
- uregs->regs[7] = PTRACE_SYSCALL_ENTER;
- break;
- case PTRACE_EVENTMSG_SYSCALL_EXIT:
- uregs->regs[7] = PTRACE_SYSCALL_EXIT;
- break;
+ if (!(target->ptrace & PT_ARM64_RAW_REGS)) {
+ /*
+ * We have some ABI weirdness here in the way that we handle
+ * syscall exit stops because we indicate whether or not the
+ * stop has been signalled from syscall entry or syscall exit
+ * by clobbering the general purpose register x7.
+ */
+ switch (target->ptrace_message) {
+ case PTRACE_EVENTMSG_SYSCALL_ENTRY:
+ uregs->regs[7] = PTRACE_SYSCALL_ENTER;
+ break;
+ case PTRACE_EVENTMSG_SYSCALL_EXIT:
+ uregs->regs[7] = PTRACE_SYSCALL_EXIT;
+ break;
+ }
}
ret = membuf_write(&to, uregs, sizeof(*uregs));@@ -600,15 +602,17 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
if (ret)
return ret;
- /*
- * Historically, x7 can't be changed if the stop has been signalled
- * from syscall-enter of syscall-exit.
- */
- switch (target->ptrace_message) {
- case PTRACE_EVENTMSG_SYSCALL_ENTRY:
- case PTRACE_EVENTMSG_SYSCALL_EXIT:
- newregs.regs[7] = task_pt_regs(target)->regs[7];
- break;
+ if (!(target->ptrace & PT_ARM64_RAW_REGS)) {
+ /*
+ * Historically, x7 can't be changed if the stop has been
+ * signalled from syscall-enter of syscall-exit.
+ */
+ switch (target->ptrace_message) {
+ case PTRACE_EVENTMSG_SYSCALL_ENTRY:
+ case PTRACE_EVENTMSG_SYSCALL_EXIT:
+ newregs.regs[7] = task_pt_regs(target)->regs[7];
+ break;
+ }
}
if (!valid_user_regs(&newregs, target))@@ -1243,6 +1247,8 @@ static inline compat_ulong_t compat_get_user_reg(struct task_struct *task, int i
switch (idx) {
case 12:
+ if (task->ptrace & PT_ARM64_RAW_REGS)
+ return regs->regs[idx];
/*
* We have some ABI weirdness here in the way that we handle
* syscall exit stops because we indicate whether or not the@@ -1332,15 +1338,17 @@ static int compat_gpr_set(struct task_struct *target,
}
- /*
- * Historically, x12 can't be changed if the stop has been signalled
- * from syscall-enter of syscall-exit.
- */
- switch (target->ptrace_message) {
- case PTRACE_EVENTMSG_SYSCALL_ENTRY:
- case PTRACE_EVENTMSG_SYSCALL_EXIT:
- newregs.regs[12] = task_pt_regs(target)->regs[12];
- break;
+ if (!(target->ptrace & PT_ARM64_RAW_REGS)) {
+ /*
+ * Historically, r12 can't be changed if the stop has been
+ * signalled from syscall-enter of syscall-exit.
+ */
+ switch (target->ptrace_message) {
+ case PTRACE_EVENTMSG_SYSCALL_ENTRY:
+ case PTRACE_EVENTMSG_SYSCALL_EXIT:
+ newregs.regs[12] = task_pt_regs(target)->regs[12];
+ break;
+ }
}
if (valid_user_regs(&newregs.user_regs, target))diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 2a9df80ea887..987d6ec5f0ce 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -46,6 +46,7 @@ extern int ptrace_access_vm(struct task_struct *tsk, unsigned long addr,
#define PT_EXITKILL (PTRACE_O_EXITKILL << PT_OPT_FLAG_SHIFT)
#define PT_SUSPEND_SECCOMP (PTRACE_O_SUSPEND_SECCOMP << PT_OPT_FLAG_SHIFT)
+#define PT_ARM64_RAW_REGS (PTRACE_O_ARM64_RAW_REGS << PT_OPT_FLAG_SHIFT)
/* single stepping state bits (used on ARM and PA-RISC) */
#define PT_SINGLESTEP_BIT 31
diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index 83ee45fa634b..bcc8c362ddd9 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -7,6 +7,7 @@
/* has the defines to get at the registers. */
#include <linux/types.h>
+#include <asm/ptrace.h>
#define PTRACE_TRACEME 0
#define PTRACE_PEEKTEXT 1
@@ -137,8 +138,14 @@ struct ptrace_syscall_info {
#define PTRACE_O_EXITKILL (1 << 20)
#define PTRACE_O_SUSPEND_SECCOMP (1 << 21)
+/* (1<<28) is reserved for arch specific options. */
+#ifndef _PTRACE_O_ARCH_OPTIONS
+#define _PTRACE_O_ARCH_OPTIONS 0
+#endif
+
#define PTRACE_O_MASK (\
- 0x000000ff | PTRACE_O_EXITKILL | PTRACE_O_SUSPEND_SECCOMP)
+ 0x000000ff | PTRACE_O_EXITKILL | \
+ PTRACE_O_SUSPEND_SECCOMP | _PTRACE_O_ARCH_OPTIONS)
#include <asm/ptrace.h>
--
2.29.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel