@@ -176,6 +176,17 @@ struct pt_regs {
#define PTRACE_GETREGS64 0x16
#define PTRACE_SETREGS64 0x17
+/*
+ * Get or set some register used bit.
+ * The flags will be saved in a 64 bit data.
+ * Currently it is only used for VR/VSR usage.
+ */
+#define PPC_PTRACE_GET_REGS_USAGE 0x97
+#define PPC_PTRACE_SET_REGS_USAGE 0x96
+
+#define PPC_PTRACE_REGS_USAGE_VR_BIT 0x01UL
+#define PPC_PTRACE_REGS_USAGE_VSR_BIT 0x02UL
+
/* Calls to trace a 64bit program from a 32bit program */
#define PPC_PTRACE_PEEKTEXT_3264 0x95
#define PPC_PTRACE_PEEKDATA_3264 0x94
@@ -3018,6 +3018,45 @@ long arch_ptrace(struct task_struct *child, long request,
REGSET_SPE, 0, 35 * sizeof(u32),
datavp);
#endif
+ case PPC_PTRACE_GET_REGS_USAGE:
+ {
+ u64 *u64_datap = (u64 *)datavp;
+ u64 reg_usage = 0;
+
+ if (addr != sizeof(u64))
+ return -EINVAL;
+
+#ifdef CONFIG_ALTIVEC
+ if (child->thread.used_vr)
+ reg_usage |= PPC_PTRACE_REGS_USAGE_VR_BIT;
+#endif
+#ifdef CONFIG_VSX
+ if (child->thread.used_vsr)
+ reg_usage |= PPC_PTRACE_REGS_USAGE_VSR_BIT;
+#endif
+ return put_user(reg_usage, u64_datap);
+ }
+ case PPC_PTRACE_SET_REGS_USAGE:
+ {
+ u64 *u64_datap = (u64 *)datavp;
+ u64 reg_usage = 0;
+
+ if (addr != sizeof(u64))
+ return -EINVAL;
+
+ ret = get_user(reg_usage, u64_datap);
+ if (ret)
+ return ret;
+#ifdef CONFIG_ALTIVEC
+ child->thread.used_vr =
+ !!(reg_usage & PPC_PTRACE_REGS_USAGE_VR_BIT);
+#endif
+#ifdef CONFIG_VSX
+ child->thread.used_vsr =
+ !!(reg_usage & PPC_PTRACE_REGS_USAGE_VSR_BIT);
+#endif
+ break;
+ }
default:
ret = ptrace_request(child, request, addr, data);
@@ -305,6 +305,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
case PPC_PTRACE_GETHWDBGINFO:
case PPC_PTRACE_SETHWDEBUG:
case PPC_PTRACE_DELHWDEBUG:
+ case PPC_PTRACE_GET_REGS_USAGE:
+ case PPC_PTRACE_SET_REGS_USAGE:
ret = arch_ptrace(child, request, addr, data);
break;