static __always_inline u64
__bpf_perf_event_output(struct pt_regs *regs, struct bpf_map *map,
			u64 flags, struct perf_raw_record *raw)
{
	struct bpf_array *array = container_of(map, struct bpf_array, map);
	unsigned int cpu = smp_processor_id();
	u64 index = flags & BPF_F_INDEX_MASK;
	struct perf_sample_data sample_data;
	struct bpf_event_entry *ee;
	struct perf_event *event;

	if (index == BPF_F_CURRENT_CPU)
		index = cpu;
	if (unlikely(index >= array->map.max_entries))
		return -E2BIG;

	ee = READ_ONCE(array->ptrs[index]);
	if (!ee)
		return -ENOENT;

	event = ee->event;
	if (unlikely(event->attr.type != PERF_TYPE_SOFTWARE ||
		     event->attr.config != PERF_COUNT_SW_BPF_OUTPUT))
		return -EINVAL;

	if (unlikely(event->oncpu != cpu))
		return -EOPNOTSUPP;

	perf_sample_data_init(&sample_data, 0, 0);
	sample_data.raw = raw;
	perf_event_output(event, &sample_data, regs);
	return 0;
}
Beispiel #2
0
static u64 bpf_perf_event_output(u64 r1, u64 r2, u64 flags, u64 r4, u64 size)
{
    struct pt_regs *regs = (struct pt_regs *) (long) r1;
    struct bpf_map *map = (struct bpf_map *) (long) r2;
    struct bpf_array *array = container_of(map, struct bpf_array, map);
    unsigned int cpu = smp_processor_id();
    u64 index = flags & BPF_F_INDEX_MASK;
    void *data = (void *) (long) r4;
    struct perf_sample_data sample_data;
    struct bpf_event_entry *ee;
    struct perf_event *event;
    struct perf_raw_record raw = {
        .size = size,
        .data = data,
    };

    if (unlikely(flags & ~(BPF_F_INDEX_MASK)))
        return -EINVAL;
    if (index == BPF_F_CURRENT_CPU)
        index = cpu;
    if (unlikely(index >= array->map.max_entries))
        return -E2BIG;

    ee = READ_ONCE(array->ptrs[index]);
    if (!ee)
        return -ENOENT;

    event = ee->event;
    if (unlikely(event->attr.type != PERF_TYPE_SOFTWARE ||
                 event->attr.config != PERF_COUNT_SW_BPF_OUTPUT))
        return -EINVAL;

    if (unlikely(event->oncpu != cpu))
        return -EOPNOTSUPP;

    perf_sample_data_init(&sample_data, 0, 0);
    sample_data.raw = &raw;
    perf_event_output(event, &sample_data, regs);
    return 0;
}