bpf: register BPF_PROG_TYPE_TRACEPOINT program type
authorAlexei Starovoitov <ast@fb.com>
Thu, 7 Apr 2016 01:43:26 +0000 (18:43 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 8 Apr 2016 01:04:26 +0000 (21:04 -0400)
register tracepoint bpf program type and let it call the same set
of helper functions as BPF_PROG_TYPE_KPROBE

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
kernel/trace/bpf_trace.c

index 3e4ffb3ace5faf371bfbfa0655a9845a96ef9c08..3e5ebe3254d280ce0dec5c86530a9a5a5704e973 100644 (file)
@@ -268,7 +268,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto = {
        .arg5_type      = ARG_CONST_STACK_SIZE,
 };
 
-static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func_id)
+static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id)
 {
        switch (func_id) {
        case BPF_FUNC_map_lookup_elem:
@@ -295,12 +295,20 @@ static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func
                return &bpf_get_smp_processor_id_proto;
        case BPF_FUNC_perf_event_read:
                return &bpf_perf_event_read_proto;
+       default:
+               return NULL;
+       }
+}
+
+static const struct bpf_func_proto *kprobe_prog_func_proto(enum bpf_func_id func_id)
+{
+       switch (func_id) {
        case BPF_FUNC_perf_event_output:
                return &bpf_perf_event_output_proto;
        case BPF_FUNC_get_stackid:
                return &bpf_get_stackid_proto;
        default:
-               return NULL;
+               return tracing_func_proto(func_id);
        }
 }
 
@@ -332,9 +340,42 @@ static struct bpf_prog_type_list kprobe_tl = {
        .type   = BPF_PROG_TYPE_KPROBE,
 };
 
+static const struct bpf_func_proto *tp_prog_func_proto(enum bpf_func_id func_id)
+{
+       switch (func_id) {
+       case BPF_FUNC_perf_event_output:
+       case BPF_FUNC_get_stackid:
+               return NULL;
+       default:
+               return tracing_func_proto(func_id);
+       }
+}
+
+static bool tp_prog_is_valid_access(int off, int size, enum bpf_access_type type)
+{
+       if (off < sizeof(void *) || off >= PERF_MAX_TRACE_SIZE)
+               return false;
+       if (type != BPF_READ)
+               return false;
+       if (off % size != 0)
+               return false;
+       return true;
+}
+
+static const struct bpf_verifier_ops tracepoint_prog_ops = {
+       .get_func_proto  = tp_prog_func_proto,
+       .is_valid_access = tp_prog_is_valid_access,
+};
+
+static struct bpf_prog_type_list tracepoint_tl = {
+       .ops    = &tracepoint_prog_ops,
+       .type   = BPF_PROG_TYPE_TRACEPOINT,
+};
+
 static int __init register_kprobe_prog_ops(void)
 {
        bpf_register_prog_type(&kprobe_tl);
+       bpf_register_prog_type(&tracepoint_tl);
        return 0;
 }
 late_initcall(register_kprobe_prog_ops);