Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / arch / x86 / include / asm / ptrace.h
index 6de1fd3d009744277c0be1593daaa380e1f0fedb..25f49af1b13c16cf562b6e9e4a4f28f88f87e3ea 100644 (file)
@@ -37,8 +37,10 @@ struct pt_regs {
        unsigned short __esh;
        unsigned short fs;
        unsigned short __fsh;
+       /* On interrupt, gs and __gsh store the vector number. */
        unsigned short gs;
        unsigned short __gsh;
+       /* On interrupt, this is the error code. */
        unsigned long orig_ax;
        unsigned long ip;
        unsigned short cs;
@@ -236,24 +238,52 @@ static inline int regs_within_kernel_stack(struct pt_regs *regs,
                (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
 }
 
+/**
+ * regs_get_kernel_stack_nth_addr() - get the address of the Nth entry on stack
+ * @regs:      pt_regs which contains kernel stack pointer.
+ * @n:         stack entry number.
+ *
+ * regs_get_kernel_stack_nth() returns the address of the @n th entry of the
+ * kernel stack which is specified by @regs. If the @n th entry is NOT in
+ * the kernel stack, this returns NULL.
+ */
+static inline unsigned long *regs_get_kernel_stack_nth_addr(struct pt_regs *regs, unsigned int n)
+{
+       unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
+
+       addr += n;
+       if (regs_within_kernel_stack(regs, (unsigned long)addr))
+               return addr;
+       else
+               return NULL;
+}
+
+/* To avoid include hell, we can't include uaccess.h */
+extern long probe_kernel_read(void *dst, const void *src, size_t size);
+
 /**
  * regs_get_kernel_stack_nth() - get Nth entry of the stack
  * @regs:      pt_regs which contains kernel stack pointer.
  * @n:         stack entry number.
  *
  * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
- * is specified by @regs. If the @n th entry is NOT in the kernel stack,
+ * is specified by @regs. If the @n th entry is NOT in the kernel stack
  * this returns 0.
  */
 static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
                                                      unsigned int n)
 {
-       unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
-       addr += n;
-       if (regs_within_kernel_stack(regs, (unsigned long)addr))
-               return *addr;
-       else
-               return 0;
+       unsigned long *addr;
+       unsigned long val;
+       long ret;
+
+       addr = regs_get_kernel_stack_nth_addr(regs, n);
+       if (addr) {
+               ret = probe_kernel_read(&val, addr, sizeof(val));
+               if (!ret)
+                       return val;
+       }
+       return 0;
 }
 
 #define arch_has_single_step() (1)