prof: samples userspace PCs
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 28 May 2014 20:47:48 +0000 (13:47 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 28 May 2014 20:47:48 +0000 (13:47 -0700)
kern/include/oprofile.h
kern/src/oprofile/cpu_buffer.c
kern/src/time.c

index 4a4d33a..ae14250 100644 (file)
@@ -107,7 +107,9 @@ void oprofile_add_ext_hw_sample(unsigned long pc, /*struct pt_regs*/void * const
 /* Use this instead when the PC value is not from the regs. Doesn't
  * backtrace. */
 void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event);
+
 void oprofile_add_backtrace(uintptr_t pc, uintptr_t fp);
+void oprofile_add_userpc(uintptr_t pc);
 
 /* add a backtrace entry, to be called from the ->backtrace callback */
 void oprofile_add_trace(unsigned long eip);
index 8f40616..d55901b 100644 (file)
@@ -714,6 +714,30 @@ fail:
        return;
 }
 
+void oprofile_add_userpc(uintptr_t pc)
+{
+       struct oprofile_cpu_buffer *cpu_buf;
+       uint32_t pcoreid = core_id();
+       struct op_entry entry;
+       struct block *b;
+       uint64_t descriptor = (0xee01ULL << 48) | (pcoreid << 16) | 1;
+
+       if (!op_cpu_buffer)
+               return;
+       cpu_buf = &op_cpu_buffer[pcoreid];
+       if (!cpu_buf->tracing)
+               return;
+       /* write_reserve always assumes passed-in-size + 2.  need room for 1 PC. */
+       b = op_cpu_buffer_write_reserve(cpu_buf, &entry, 1);
+       if (!b)
+               return;
+       entry.sample->eip = descriptor;
+       entry.sample->event = nsec();
+       /* entry.sample->data == entry.data */
+       assert(entry.sample->data == entry.data);
+       *entry.sample->data = pc;
+}
+
 int
 oproflen(void)
 {
index 083ecfe..a195873 100644 (file)
@@ -58,7 +58,8 @@ void timer_interrupt(struct hw_trapframe *hw_tf, void *data)
 {
        if (in_kernel(hw_tf))
                oprofile_add_backtrace(get_hwtf_pc(hw_tf), get_hwtf_fp(hw_tf));
-       // else add user_sample or something
+       else
+               oprofile_add_userpc(get_hwtf_pc(hw_tf));
 
        int coreid = core_id();
        /* run the alarms out of RKM context, so that event delivery works nicely