summaryrefslogtreecommitdiff
path: root/module
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2005-11-13 00:46:08 +0000
committerSøren Sandmann Pedersen <ssp@src.gnome.org>2005-11-13 00:46:08 +0000
commit3a306d20d000428c8185007064946d7831746db4 (patch)
treec6acd386bf691657cc7352ff6aaa6355d61ff870 /module
parentc3ce4ef8c56f7d85e9adc9f63c8dbccf3d7b44a5 (diff)
great-sage-equal-to-heaven:~/vertigo/sysprof% head -13 ChangeLog
Sat Nov 12 19:44:43 2005 Søren Sandmann <sandmann@redhat.com> * module/sysprof-module.c (read_frame): New function that uses copy_from_user_inatomic() as check_user_pages_readable() has disappeared in recent kernels. * module/sysprof-module.c (timer_notify): Use it here. * TODO: Updates * configure.ac: Change the wording of the CVS HEAD warning as this change seems to also have fixed the lockup with rawhide kernels.
Diffstat (limited to 'module')
-rw-r--r--module/sysprof-module.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/module/sysprof-module.c b/module/sysprof-module.c
index c682eed..1fc01b7 100644
--- a/module/sysprof-module.c
+++ b/module/sysprof-module.c
@@ -220,6 +220,27 @@ static int pages_present(StackFrame * head)
}
#endif /* CONFIG_X86_4G */
+static int
+read_frame (void *frame_pointer, StackFrame *frame)
+{
+#if 0
+ /* This is commented out because we seem to be called with
+ * (current_thread_info()->addr_limit.seg)) == 0
+ * which means access_ok() _always_ fails.
+ *
+ * Not sure why (or even if) this isn't the case for oprofile
+ */
+ if (!access_ok(VERIFY_READ, frame_pointer, sizeof(StackFrame)))
+ return 1;
+#endif
+
+ if (__copy_from_user_inatomic (
+ frame, frame_pointer, sizeof (StackFrame)))
+ return 2;
+
+ return 0;
+}
+
static int timer_notify (struct pt_regs *regs)
{
#ifdef CONFIG_HIGHMEM
@@ -227,7 +248,7 @@ static int timer_notify (struct pt_regs *regs)
#else
# define START_OF_STACK 0xBFFFFFFF
#endif
- StackFrame *frame;
+ void *frame_pointer;
static int n_samples;
SysprofStackTrace *trace = head;
int i;
@@ -256,17 +277,39 @@ static int timer_notify (struct pt_regs *regs)
}
trace->addresses[i++] = (void *)regs->REG_INS_PTR;
-
- frame = (StackFrame *)regs->REG_FRAME_PTR;
-
- while (pages_present (frame) &&
- i < SYSPROF_MAX_ADDRESSES &&
- ((unsigned long)frame) < START_OF_STACK &&
- (unsigned long)frame >= regs->REG_STACK_PTR)
+
+#if 0
+ if (is_user)
{
- trace->addresses[i++] = (void *)frame->return_address;
- frame = (StackFrame *)frame->next;
+#endif
+ StackFrame frame;
+ int result;
+
+ frame_pointer = (void *)regs->REG_FRAME_PTR;
+
+ while (((result = read_frame (frame_pointer, &frame)) == 0) &&
+ i < SYSPROF_MAX_ADDRESSES &&
+ ((unsigned long)frame_pointer) < START_OF_STACK &&
+ (unsigned long)frame_pointer >= regs->REG_STACK_PTR)
+ {
+ trace->addresses[i++] = (void *)frame.return_address;
+ frame_pointer = (StackFrame *)frame.next;
+ }
+
+#if 0
+ if (result) {
+ trace->addresses[i++] = (void *)0x23456789;
+ trace->addresses[i++] = current_thread_info()->addr_limit.seg;
+ trace->addresses[i++] = regs->REG_FRAME_PTR;
+ trace->addresses[i++] = result;
+ trace->addresses[i++] = 0x98765432;
+ }
+ else
+ trace->addresses[i++] = 0x10101010;
+#endif
+#if 0
}
+#endif
trace->n_addresses = i;