History

perf: Add generic memory sampling interface

This patch adds PERF_SAMPLE_DATA_SRC. PERF_SAMPLE_DATA_SRC collects the data source, i.e., where did the data associated with the sampled instruction come from. Information is stored in a perf_mem_data_src structure. It contains opcode, mem level, tlb, snoop, lock information, subject to availability in hardware.

Stephane Eranian committed 13 years ago

Commit d6be9ad1 parent c3feedf3 files · +74 −2Browse files

Unified · Split

3 files
  1. include/linux/perf_event.h +2 −0
  2. include/uapi/linux/perf_event.h +66 −2
  3. kernel/events/core.c +6 −0
include/linux/perf_event.h+2−0
@@ -568,6 +568,7 @@ struct perf_sample_data { · 567 unmodified lines
568568 u32 reserved;
569569 } cpu_entry;
570570 u64 period;
571+ union perf_mem_data_src data_src;
571572 struct perf_callchain_entry *callchain;
572573 struct perf_raw_record *raw;
573574 struct perf_branch_stack *br_stack;
@@ -588,6 +589,7 @@ static inline void perf_sample_data_init(struct perf_sample_data *data, · 14 unmodified lines
588589 data->regs_user.regs = NULL;
589590 data->stack_user_size = 0;
590591 data->weight = 0;
592+ data->data_src.val = 0;
591593 }
592594
593595 extern void perf_output_sample(struct perf_output_handle *handle,
include/uapi/linux/perf_event.h+66−2
@@ -133,9 +133,9 @@ enum perf_event_sample_format { · 132 unmodified lines
133133 PERF_SAMPLE_REGS_USER = 1U << 12,
134134 PERF_SAMPLE_STACK_USER = 1U << 13,
135135 PERF_SAMPLE_WEIGHT = 1U << 14,
136+ PERF_SAMPLE_DATA_SRC = 1U << 15,
136137
137− PERF_SAMPLE_MAX = 1U << 15, /* non-ABI */
138−
138+ PERF_SAMPLE_MAX = 1U << 16, /* non-ABI */
139139 };
140140
141141 /*
@@ -592,6 +592,7 @@ enum perf_event_type { · 450 unmodified lines
592592 * u64 dyn_size; } && PERF_SAMPLE_STACK_USER
593593 *
594594 * { u64 weight; } && PERF_SAMPLE_WEIGHT
595+ * { u64 data_src; } && PERF_SAMPLE_DATA_SRC
595596 * };
596597 */
597598 PERF_RECORD_SAMPLE = 9,
@@ -617,4 +618,67 @@ enum perf_callchain_context { · 19 unmodified lines
617618 #define PERF_FLAG_FD_OUTPUT (1U << 1)
618619 #define PERF_FLAG_PID_CGROUP (1U << 2) /* pid=cgroup id, per-cpu mode only */
619620
621+union perf_mem_data_src {
622+ __u64 val;
623+ struct {
624+ __u64 mem_op:5, /* type of opcode */
625+ mem_lvl:14, /* memory hierarchy level */
626+ mem_snoop:5, /* snoop mode */
627+ mem_lock:2, /* lock instr */
628+ mem_dtlb:7, /* tlb access */
629+ mem_rsvd:31;
630+ };
631+};
632+
633+/* type of opcode (load/store/prefetch,code) */
634+#define PERF_MEM_OP_NA 0x01 /* not available */
635+#define PERF_MEM_OP_LOAD 0x02 /* load instruction */
636+#define PERF_MEM_OP_STORE 0x04 /* store instruction */
637+#define PERF_MEM_OP_PFETCH 0x08 /* prefetch */
638+#define PERF_MEM_OP_EXEC 0x10 /* code (execution) */
639+#define PERF_MEM_OP_SHIFT 0
640+
641+/* memory hierarchy (memory level, hit or miss) */
642+#define PERF_MEM_LVL_NA 0x01 /* not available */
643+#define PERF_MEM_LVL_HIT 0x02 /* hit level */
644+#define PERF_MEM_LVL_MISS 0x04 /* miss level */
645+#define PERF_MEM_LVL_L1 0x08 /* L1 */
646+#define PERF_MEM_LVL_LFB 0x10 /* Line Fill Buffer */
647+#define PERF_MEM_LVL_L2 0x20 /* L2 hit */
648+#define PERF_MEM_LVL_L3 0x40 /* L3 hit */
649+#define PERF_MEM_LVL_LOC_RAM 0x80 /* Local DRAM */
650+#define PERF_MEM_LVL_REM_RAM1 0x100 /* Remote DRAM (1 hop) */
651+#define PERF_MEM_LVL_REM_RAM2 0x200 /* Remote DRAM (2 hops) */
652+#define PERF_MEM_LVL_REM_CCE1 0x400 /* Remote Cache (1 hop) */
653+#define PERF_MEM_LVL_REM_CCE2 0x800 /* Remote Cache (2 hops) */
654+#define PERF_MEM_LVL_IO 0x1000 /* I/O memory */
655+#define PERF_MEM_LVL_UNC 0x2000 /* Uncached memory */
656+#define PERF_MEM_LVL_SHIFT 5
657+
658+/* snoop mode */
659+#define PERF_MEM_SNOOP_NA 0x01 /* not available */
660+#define PERF_MEM_SNOOP_NONE 0x02 /* no snoop */
661+#define PERF_MEM_SNOOP_HIT 0x04 /* snoop hit */
662+#define PERF_MEM_SNOOP_MISS 0x08 /* snoop miss */
663+#define PERF_MEM_SNOOP_HITM 0x10 /* snoop hit modified */
664+#define PERF_MEM_SNOOP_SHIFT 19
665+
666+/* locked instruction */
667+#define PERF_MEM_LOCK_NA 0x01 /* not available */
668+#define PERF_MEM_LOCK_LOCKED 0x02 /* locked transaction */
669+#define PERF_MEM_LOCK_SHIFT 24
670+
671+/* TLB access */
672+#define PERF_MEM_TLB_NA 0x01 /* not available */
673+#define PERF_MEM_TLB_HIT 0x02 /* hit level */
674+#define PERF_MEM_TLB_MISS 0x04 /* miss level */
675+#define PERF_MEM_TLB_L1 0x08 /* L1 */
676+#define PERF_MEM_TLB_L2 0x10 /* L2 */
677+#define PERF_MEM_TLB_WK 0x20 /* Hardware Walker*/
678+#define PERF_MEM_TLB_OS 0x40 /* OS fault handler */
679+#define PERF_MEM_TLB_SHIFT 26
680+
681+#define PERF_MEM_S(a, s) \
682+ (((u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT)
683+
620684 #endif /* _UAPI_LINUX_PERF_EVENT_H */
kernel/events/core.c+6−0
@@ -982,6 +982,9 @@ static void perf_event__header_size(struct perf_event *event) · 981 unmodified lines
982982 if (sample_type & PERF_SAMPLE_READ)
983983 size += event->read_size;
984984
985+ if (sample_type & PERF_SAMPLE_DATA_SRC)
986+ size += sizeof(data->data_src.val);
987+
985988 event->header_size = size;
986989 }
987990
@@ -4199,6 +4202,9 @@ void perf_output_sample(struct perf_output_handle *handle, · 3211 unmodified lines
41994202
42004203 if (sample_type & PERF_SAMPLE_WEIGHT)
42014204 perf_output_put(handle, data->weight);
4205+
4206+ if (sample_type & PERF_SAMPLE_DATA_SRC)
4207+ perf_output_put(handle, data->data_src.val);
42024208 }
42034209
42044210 void perf_prepare_sample(struct perf_event_header *header,