perf build: Add ability to build with a generated vmlinux.h
authorIan Rogers <irogers@google.com>
Fri, 23 Jun 2023 04:14:02 +0000 (21:14 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Sat, 24 Jun 2023 04:35:45 +0000 (21:35 -0700)
Commit a887466562b4 ("perf bpf skels: Stop using vmlinux.h generated
from BTF, use subset of used structs + CO-RE") made it so that
vmlinux.h was uncondtionally included from
tools/perf/util/vmlinux.h. This change reverts part of that change (so
that vmlinux.h is once again generated) and makes it so that the
vmlinux.h used at build time is selected from the VMLINUX_H
variable. By default the VMLINUX_H variable is set to the vmlinux.h
added in change a887466562b4, but if GEN_VMLINUX_H=1 is passed on the
build command line then the previous generation behavior kicks in.

The build with GEN_VMLINUX_H=1 currently fails with:

    util/bpf_skel/lock_contention.bpf.c:419:8: error: redefinition of 'rq'
    struct rq {};
           ^
    /tmp/perf/util/bpf_skel/.tmp/../vmlinux.h:45630:8: note: previous definition is here
    struct rq {
           ^
    1 error generated.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Cc: James Clark <james.clark@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Tiezhu Yang <yangtiezhu@loongson.cn>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: bpf@vger.kernel.org
Link: https://lore.kernel.org/r/20230623041405.4039475-2-irogers@google.com
[ Format the error message and add a comment for GEN_VMLINUX_H ]
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/Makefile.config
tools/perf/Makefile.perf
tools/perf/util/bpf_skel/.gitignore
tools/perf/util/bpf_skel/vmlinux.h [deleted file]
tools/perf/util/bpf_skel/vmlinux/vmlinux.h [new file with mode: 0644]

index 9c5aa14..7841125 100644 (file)
@@ -680,6 +680,10 @@ ifdef BUILD_BPF_SKEL
   CFLAGS += -DHAVE_BPF_SKEL
 endif
 
+ifndef GEN_VMLINUX_H
+  VMLINUX_H=$(src-perf)/util/bpf_skel/vmlinux/vmlinux.h
+endif
+
 dwarf-post-unwind := 1
 dwarf-post-unwind-text := BUG
 
index b1e62a6..a49eded 100644 (file)
@@ -132,6 +132,8 @@ include ../scripts/utilities.mak
 # Define EXTRA_TESTS to enable building extra tests useful mainly to perf
 # developers, such as:
 #      x86 instruction decoder - new instructions test
+#
+# Define GEN_VMLINUX_H to generate vmlinux.h from the BTF.
 
 # As per kernel Makefile, avoid funny character set dependencies
 unexport LC_ALL
@@ -1084,7 +1086,21 @@ $(BPFTOOL): | $(SKEL_TMP_OUT)
        $(Q)CFLAGS= $(MAKE) -C ../bpf/bpftool \
                OUTPUT=$(SKEL_TMP_OUT)/ bootstrap
 
-$(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF) | $(SKEL_TMP_OUT)
+VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux)                           \
+                    $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux)    \
+                    ../../vmlinux                                      \
+                    /sys/kernel/btf/vmlinux                            \
+                    /boot/vmlinux-$(shell uname -r)
+VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS))))
+
+$(SKEL_OUT)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL)
+ifeq ($(VMLINUX_H),)
+       $(QUIET_GEN)$(BPFTOOL) btf dump file $< format c > $@
+else
+       $(Q)cp "$(VMLINUX_H)" $@
+endif
+
+$(SKEL_TMP_OUT)/%.bpf.o: util/bpf_skel/%.bpf.c $(LIBBPF) $(SKEL_OUT)/vmlinux.h | $(SKEL_TMP_OUT)
        $(QUIET_CLANG)$(CLANG) -g -O2 -target bpf -Wall -Werror $(BPF_INCLUDE) $(TOOLS_UAPI_INCLUDE) \
          -c $(filter util/bpf_skel/%.bpf.c,$^) -o $@
 
index 7a1c832..cd01455 100644 (file)
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 .tmp
 *.skel.h
+vmlinux.h
diff --git a/tools/perf/util/bpf_skel/vmlinux.h b/tools/perf/util/bpf_skel/vmlinux.h
deleted file mode 100644 (file)
index c7ed51b..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-#ifndef __VMLINUX_H
-#define __VMLINUX_H
-
-#include <linux/stddef.h> // for define __always_inline
-#include <linux/bpf.h>
-#include <linux/types.h>
-#include <linux/perf_event.h>
-#include <stdbool.h>
-
-// non-UAPI kernel data structures, used in the .bpf.c BPF tool component.
-
-// Just the fields used in these tools preserving the access index so that
-// libbpf can fixup offsets with the ones used in the kernel when loading the
-// BPF bytecode, if they differ from what is used here.
-
-typedef __u8 u8;
-typedef __u32 u32;
-typedef __u64 u64;
-typedef __s64 s64;
-
-typedef int pid_t;
-
-enum cgroup_subsys_id {
-       perf_event_cgrp_id  = 8,
-};
-
-enum {
-       HI_SOFTIRQ = 0,
-       TIMER_SOFTIRQ,
-       NET_TX_SOFTIRQ,
-       NET_RX_SOFTIRQ,
-       BLOCK_SOFTIRQ,
-       IRQ_POLL_SOFTIRQ,
-       TASKLET_SOFTIRQ,
-       SCHED_SOFTIRQ,
-       HRTIMER_SOFTIRQ,
-       RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */
-
-       NR_SOFTIRQS
-};
-
-typedef struct {
-       s64     counter;
-} __attribute__((preserve_access_index)) atomic64_t;
-
-typedef atomic64_t atomic_long_t;
-
-struct raw_spinlock {
-       int rawlock;
-} __attribute__((preserve_access_index));
-
-typedef struct raw_spinlock raw_spinlock_t;
-
-typedef struct {
-       struct raw_spinlock rlock;
-} __attribute__((preserve_access_index)) spinlock_t;
-
-struct sighand_struct {
-       spinlock_t siglock;
-} __attribute__((preserve_access_index));
-
-struct rw_semaphore {
-       atomic_long_t owner;
-} __attribute__((preserve_access_index));
-
-struct mutex {
-       atomic_long_t owner;
-} __attribute__((preserve_access_index));
-
-struct kernfs_node {
-       u64 id;
-} __attribute__((preserve_access_index));
-
-struct cgroup {
-       struct kernfs_node *kn;
-       int                level;
-}  __attribute__((preserve_access_index));
-
-struct cgroup_subsys_state {
-       struct cgroup *cgroup;
-} __attribute__((preserve_access_index));
-
-struct css_set {
-       struct cgroup_subsys_state *subsys[13];
-       struct cgroup *dfl_cgrp;
-} __attribute__((preserve_access_index));
-
-struct mm_struct {
-       struct rw_semaphore mmap_lock;
-} __attribute__((preserve_access_index));
-
-struct task_struct {
-       unsigned int          flags;
-       struct mm_struct      *mm;
-       pid_t                 pid;
-       pid_t                 tgid;
-       char                  comm[16];
-       struct sighand_struct *sighand;
-       struct css_set        *cgroups;
-} __attribute__((preserve_access_index));
-
-struct trace_entry {
-       short unsigned int type;
-       unsigned char      flags;
-       unsigned char      preempt_count;
-       int                pid;
-} __attribute__((preserve_access_index));
-
-struct trace_event_raw_irq_handler_entry {
-       struct trace_entry ent;
-       int                irq;
-       u32                __data_loc_name;
-       char               __data[];
-} __attribute__((preserve_access_index));
-
-struct trace_event_raw_irq_handler_exit {
-       struct trace_entry ent;
-       int                irq;
-       int                ret;
-       char               __data[];
-} __attribute__((preserve_access_index));
-
-struct trace_event_raw_softirq {
-       struct trace_entry ent;
-       unsigned int       vec;
-       char               __data[];
-} __attribute__((preserve_access_index));
-
-struct trace_event_raw_workqueue_execute_start {
-       struct trace_entry ent;
-       void               *work;
-       void               *function;
-       char               __data[];
-} __attribute__((preserve_access_index));
-
-struct trace_event_raw_workqueue_execute_end {
-       struct trace_entry ent;
-       void               *work;
-       void               *function;
-       char              __data[];
-} __attribute__((preserve_access_index));
-
-struct trace_event_raw_workqueue_activate_work {
-       struct trace_entry ent;
-       void               *work;
-       char               __data[];
-} __attribute__((preserve_access_index));
-
-struct perf_sample_data {
-       u64                      addr;
-       u64                      period;
-       union perf_sample_weight weight;
-       u64                      txn;
-       union perf_mem_data_src  data_src;
-       u64                      ip;
-       struct {
-               u32              pid;
-               u32              tid;
-       } tid_entry;
-       u64                      time;
-       u64                      id;
-       struct {
-               u32              cpu;
-       } cpu_entry;
-       u64                      phys_addr;
-       u64                      data_page_size;
-       u64                      code_page_size;
-} __attribute__((__aligned__(64))) __attribute__((preserve_access_index));
-
-struct bpf_perf_event_data_kern {
-       struct perf_sample_data *data;
-       struct perf_event       *event;
-} __attribute__((preserve_access_index));
-#endif // __VMLINUX_H
diff --git a/tools/perf/util/bpf_skel/vmlinux/vmlinux.h b/tools/perf/util/bpf_skel/vmlinux/vmlinux.h
new file mode 100644 (file)
index 0000000..c7ed51b
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef __VMLINUX_H
+#define __VMLINUX_H
+
+#include <linux/stddef.h> // for define __always_inline
+#include <linux/bpf.h>
+#include <linux/types.h>
+#include <linux/perf_event.h>
+#include <stdbool.h>
+
+// non-UAPI kernel data structures, used in the .bpf.c BPF tool component.
+
+// Just the fields used in these tools preserving the access index so that
+// libbpf can fixup offsets with the ones used in the kernel when loading the
+// BPF bytecode, if they differ from what is used here.
+
+typedef __u8 u8;
+typedef __u32 u32;
+typedef __u64 u64;
+typedef __s64 s64;
+
+typedef int pid_t;
+
+enum cgroup_subsys_id {
+       perf_event_cgrp_id  = 8,
+};
+
+enum {
+       HI_SOFTIRQ = 0,
+       TIMER_SOFTIRQ,
+       NET_TX_SOFTIRQ,
+       NET_RX_SOFTIRQ,
+       BLOCK_SOFTIRQ,
+       IRQ_POLL_SOFTIRQ,
+       TASKLET_SOFTIRQ,
+       SCHED_SOFTIRQ,
+       HRTIMER_SOFTIRQ,
+       RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */
+
+       NR_SOFTIRQS
+};
+
+typedef struct {
+       s64     counter;
+} __attribute__((preserve_access_index)) atomic64_t;
+
+typedef atomic64_t atomic_long_t;
+
+struct raw_spinlock {
+       int rawlock;
+} __attribute__((preserve_access_index));
+
+typedef struct raw_spinlock raw_spinlock_t;
+
+typedef struct {
+       struct raw_spinlock rlock;
+} __attribute__((preserve_access_index)) spinlock_t;
+
+struct sighand_struct {
+       spinlock_t siglock;
+} __attribute__((preserve_access_index));
+
+struct rw_semaphore {
+       atomic_long_t owner;
+} __attribute__((preserve_access_index));
+
+struct mutex {
+       atomic_long_t owner;
+} __attribute__((preserve_access_index));
+
+struct kernfs_node {
+       u64 id;
+} __attribute__((preserve_access_index));
+
+struct cgroup {
+       struct kernfs_node *kn;
+       int                level;
+}  __attribute__((preserve_access_index));
+
+struct cgroup_subsys_state {
+       struct cgroup *cgroup;
+} __attribute__((preserve_access_index));
+
+struct css_set {
+       struct cgroup_subsys_state *subsys[13];
+       struct cgroup *dfl_cgrp;
+} __attribute__((preserve_access_index));
+
+struct mm_struct {
+       struct rw_semaphore mmap_lock;
+} __attribute__((preserve_access_index));
+
+struct task_struct {
+       unsigned int          flags;
+       struct mm_struct      *mm;
+       pid_t                 pid;
+       pid_t                 tgid;
+       char                  comm[16];
+       struct sighand_struct *sighand;
+       struct css_set        *cgroups;
+} __attribute__((preserve_access_index));
+
+struct trace_entry {
+       short unsigned int type;
+       unsigned char      flags;
+       unsigned char      preempt_count;
+       int                pid;
+} __attribute__((preserve_access_index));
+
+struct trace_event_raw_irq_handler_entry {
+       struct trace_entry ent;
+       int                irq;
+       u32                __data_loc_name;
+       char               __data[];
+} __attribute__((preserve_access_index));
+
+struct trace_event_raw_irq_handler_exit {
+       struct trace_entry ent;
+       int                irq;
+       int                ret;
+       char               __data[];
+} __attribute__((preserve_access_index));
+
+struct trace_event_raw_softirq {
+       struct trace_entry ent;
+       unsigned int       vec;
+       char               __data[];
+} __attribute__((preserve_access_index));
+
+struct trace_event_raw_workqueue_execute_start {
+       struct trace_entry ent;
+       void               *work;
+       void               *function;
+       char               __data[];
+} __attribute__((preserve_access_index));
+
+struct trace_event_raw_workqueue_execute_end {
+       struct trace_entry ent;
+       void               *work;
+       void               *function;
+       char              __data[];
+} __attribute__((preserve_access_index));
+
+struct trace_event_raw_workqueue_activate_work {
+       struct trace_entry ent;
+       void               *work;
+       char               __data[];
+} __attribute__((preserve_access_index));
+
+struct perf_sample_data {
+       u64                      addr;
+       u64                      period;
+       union perf_sample_weight weight;
+       u64                      txn;
+       union perf_mem_data_src  data_src;
+       u64                      ip;
+       struct {
+               u32              pid;
+               u32              tid;
+       } tid_entry;
+       u64                      time;
+       u64                      id;
+       struct {
+               u32              cpu;
+       } cpu_entry;
+       u64                      phys_addr;
+       u64                      data_page_size;
+       u64                      code_page_size;
+} __attribute__((__aligned__(64))) __attribute__((preserve_access_index));
+
+struct bpf_perf_event_data_kern {
+       struct perf_sample_data *data;
+       struct perf_event       *event;
+} __attribute__((preserve_access_index));
+#endif // __VMLINUX_H