Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 721daebb authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bpf-perf'

Alexei Starovoitov says:

====================
bpf_perf_event_output helper

Over the last year there were multiple attempts to let eBPF programs
output data into perf events by He Kuang and Wangnan.
The last one was:
https://lkml.org/lkml/2015/7/20/736


It was almost perfect with exception that all bpf programs would sent
data into one global perf_event.
This patch set takes different approach by letting user space
open independent PERF_COUNT_SW_BPF_OUTPUT events, so that program
output won't collide.

Wangnan is working on corresponding perf patches.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 63b11e75 39111695
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -287,6 +287,17 @@ enum bpf_func_id {
	 * Return: realm if != 0
	 */
	BPF_FUNC_get_route_realm,

	/**
	 * bpf_perf_event_output(ctx, map, index, data, size) - output perf raw sample
	 * @ctx: struct pt_regs*
	 * @map: pointer to perf_event_array map
	 * @index: index of event in the map
	 * @data: data on stack to be output as raw data
	 * @size: size of data
	 * Return: 0 on success
	 */
	BPF_FUNC_perf_event_output,
	__BPF_FUNC_MAX_ID,
};

+1 −0
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ enum perf_sw_ids {
	PERF_COUNT_SW_ALIGNMENT_FAULTS		= 7,
	PERF_COUNT_SW_EMULATION_FAULTS		= 8,
	PERF_COUNT_SW_DUMMY			= 9,
	PERF_COUNT_SW_BPF_OUTPUT		= 10,

	PERF_COUNT_SW_MAX,			/* non-ABI */
};
+2 −0
Original line number Diff line number Diff line
@@ -295,6 +295,8 @@ static void *perf_event_fd_array_get_ptr(struct bpf_map *map, int fd)
		return (void *)attr;

	if (attr->type != PERF_TYPE_RAW &&
	    !(attr->type == PERF_TYPE_SOFTWARE &&
	      attr->config == PERF_COUNT_SW_BPF_OUTPUT) &&
	    attr->type != PERF_TYPE_HARDWARE) {
		perf_event_release_kernel(event);
		return ERR_PTR(-EINVAL);
+2 −1
Original line number Diff line number Diff line
@@ -245,6 +245,7 @@ static const struct {
} func_limit[] = {
	{BPF_MAP_TYPE_PROG_ARRAY, BPF_FUNC_tail_call},
	{BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_read},
	{BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_output},
};

static void print_verifier_state(struct verifier_env *env)
@@ -910,7 +911,7 @@ static int check_map_func_compatibility(struct bpf_map *map, int func_id)
		 * don't allow any other map type to be passed into
		 * the special func;
		 */
		if (bool_map != bool_func)
		if (bool_func && bool_map != bool_func)
			return -EINVAL;
	}

+10 −5
Original line number Diff line number Diff line
@@ -5286,9 +5286,15 @@ void perf_output_sample(struct perf_output_handle *handle,

	if (sample_type & PERF_SAMPLE_RAW) {
		if (data->raw) {
			perf_output_put(handle, data->raw->size);
			__output_copy(handle, data->raw->data,
					   data->raw->size);
			u32 raw_size = data->raw->size;
			u32 real_size = round_up(raw_size + sizeof(u32),
						 sizeof(u64)) - sizeof(u32);
			u64 zero = 0;

			perf_output_put(handle, real_size);
			__output_copy(handle, data->raw->data, raw_size);
			if (real_size - raw_size)
				__output_copy(handle, &zero, real_size - raw_size);
		} else {
			struct {
				u32	size;
@@ -5420,8 +5426,7 @@ void perf_prepare_sample(struct perf_event_header *header,
		else
			size += sizeof(u32);

		WARN_ON_ONCE(size & (sizeof(u64)-1));
		header->size += size;
		header->size += round_up(size, sizeof(u64));
	}

	if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
Loading