1# SPDX-License-Identifier: GPL-2.0 2# Copyright (c) 2022 Meta Platforms, Inc. and affiliates. 3include ../../../build/Build.include 4include ../../../scripts/Makefile.arch 5include ../../../scripts/Makefile.include 6 7TEST_GEN_PROGS := runner 8 9# override lib.mk's default rules 10OVERRIDE_TARGETS := 1 11include ../lib.mk 12 13CURDIR := $(abspath .) 14REPOROOT := $(abspath ../../../..) 15TOOLSDIR := $(REPOROOT)/tools 16LIBDIR := $(TOOLSDIR)/lib 17BPFDIR := $(LIBDIR)/bpf 18TOOLSINCDIR := $(TOOLSDIR)/include 19BPFTOOLDIR := $(TOOLSDIR)/bpf/bpftool 20APIDIR := $(TOOLSINCDIR)/uapi 21GENDIR := $(REPOROOT)/include/generated 22GENHDR := $(GENDIR)/autoconf.h 23SCXTOOLSDIR := $(TOOLSDIR)/sched_ext 24SCXTOOLSINCDIR := $(TOOLSDIR)/sched_ext/include 25 26OUTPUT_DIR := $(OUTPUT)/build 27OBJ_DIR := $(OUTPUT_DIR)/obj 28INCLUDE_DIR := $(OUTPUT_DIR)/include 29BPFOBJ_DIR := $(OBJ_DIR)/libbpf 30SCXOBJ_DIR := $(OBJ_DIR)/sched_ext 31BPFOBJ := $(BPFOBJ_DIR)/libbpf.a 32LIBBPF_OUTPUT := $(OBJ_DIR)/libbpf/libbpf.a 33 34DEFAULT_BPFTOOL := $(OUTPUT_DIR)/host/sbin/bpftool 35HOST_OBJ_DIR := $(OBJ_DIR)/host/bpftool 36HOST_LIBBPF_OUTPUT := $(OBJ_DIR)/host/libbpf/ 37HOST_LIBBPF_DESTDIR := $(OUTPUT_DIR)/host/ 38HOST_DESTDIR := $(OUTPUT_DIR)/host/ 39 40VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux) \ 41 $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux) \ 42 ../../../../vmlinux \ 43 /sys/kernel/btf/vmlinux \ 44 /boot/vmlinux-$(shell uname -r) 45VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS)))) 46ifeq ($(VMLINUX_BTF),) 47$(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)") 48endif 49 50BPFTOOL ?= $(DEFAULT_BPFTOOL) 51 52ifneq ($(wildcard $(GENHDR)),) 53 GENFLAGS := -DHAVE_GENHDR 54endif 55 56CFLAGS += -g -O2 -rdynamic -pthread -Wall -Werror $(GENFLAGS) \ 57 -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \ 58 -I$(TOOLSINCDIR) -I$(APIDIR) -I$(CURDIR)/include -I$(SCXTOOLSINCDIR) 59 60# Silence some warnings when compiled with clang 61ifneq ($(LLVM),) 62CFLAGS += -Wno-unused-command-line-argument 63endif 64 65LDFLAGS = -lelf -lz -lpthread -lzstd 66 67IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - </dev/null | \ 68 grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__') 69 70# Get Clang's default includes on this system, as opposed to those seen by 71# '-target bpf'. This fixes "missing" files on some architectures/distros, 72# such as asm/byteorder.h, asm/socket.h, asm/sockios.h, sys/cdefs.h etc. 73# 74# Use '-idirafter': Don't interfere with include mechanics except where the 75# build would have failed anyways. 76define get_sys_includes 77$(shell $(1) $(2) -v -E - </dev/null 2>&1 \ 78 | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \ 79$(shell $(1) $(2) -dM -E - </dev/null | grep '__riscv_xlen ' | awk '{printf("-D__riscv_xlen=%d -D__BITS_PER_LONG=%d", $$3, $$3)}') 80endef 81 82ifneq ($(CROSS_COMPILE),) 83CLANG_TARGET_ARCH = --target=$(notdir $(CROSS_COMPILE:%-=%)) 84endif 85 86CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH)) 87 88BPF_CFLAGS = -g -D__TARGET_ARCH_$(SRCARCH) \ 89 $(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian) \ 90 -I$(CURDIR)/include -I$(CURDIR)/include/bpf-compat \ 91 -I$(INCLUDE_DIR) -I$(APIDIR) -I$(SCXTOOLSINCDIR) \ 92 -I$(REPOROOT)/include \ 93 $(CLANG_SYS_INCLUDES) \ 94 -Wall -Wno-compare-distinct-pointer-types \ 95 -Wno-incompatible-function-pointer-types \ 96 -O2 -mcpu=v3 97 98# sort removes libbpf duplicates when not cross-building 99MAKE_DIRS := $(sort $(OBJ_DIR)/libbpf $(OBJ_DIR)/libbpf \ 100 $(OBJ_DIR)/bpftool $(OBJ_DIR)/resolve_btfids \ 101 $(HOST_OBJ_DIR) $(INCLUDE_DIR) $(SCXOBJ_DIR)) 102 103$(MAKE_DIRS): 104 $(call msg,MKDIR,,$@) 105 $(Q)mkdir -p $@ 106 107$(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ 108 $(APIDIR)/linux/bpf.h \ 109 | $(OBJ_DIR)/libbpf 110 $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) OUTPUT=$(OBJ_DIR)/libbpf/ \ 111 ARCH=$(ARCH) CC="$(CC)" CROSS_COMPILE=$(CROSS_COMPILE) \ 112 EXTRA_CFLAGS='-g -O0 -fPIC' \ 113 DESTDIR=$(OUTPUT_DIR) prefix= all install_headers 114 115$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \ 116 $(LIBBPF_OUTPUT) | $(HOST_OBJ_DIR) 117 $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \ 118 ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) \ 119 EXTRA_CFLAGS='-g -O0' \ 120 OUTPUT=$(HOST_OBJ_DIR)/ \ 121 LIBBPF_OUTPUT=$(HOST_LIBBPF_OUTPUT) \ 122 LIBBPF_DESTDIR=$(HOST_LIBBPF_DESTDIR) \ 123 prefix= DESTDIR=$(HOST_DESTDIR) install-bin 124 125$(INCLUDE_DIR)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR) 126ifeq ($(VMLINUX_H),) 127 $(call msg,GEN,,$@) 128 $(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@ 129else 130 $(call msg,CP,,$@) 131 $(Q)cp "$(VMLINUX_H)" $@ 132endif 133 134$(SCXOBJ_DIR)/%.bpf.o: %.bpf.c $(INCLUDE_DIR)/vmlinux.h | $(BPFOBJ) $(SCXOBJ_DIR) 135 $(call msg,CLNG-BPF,,$(notdir $@)) 136 $(Q)$(CLANG) $(BPF_CFLAGS) -target bpf -c $< -o $@ 137 138$(INCLUDE_DIR)/%.bpf.skel.h: $(SCXOBJ_DIR)/%.bpf.o $(INCLUDE_DIR)/vmlinux.h $(BPFTOOL) | $(INCLUDE_DIR) 139 $(eval sched=$(notdir $@)) 140 $(call msg,GEN-SKEL,,$(sched)) 141 $(Q)$(BPFTOOL) gen object $(<:.o=.linked1.o) $< 142 $(Q)$(BPFTOOL) gen object $(<:.o=.linked2.o) $(<:.o=.linked1.o) 143 $(Q)$(BPFTOOL) gen object $(<:.o=.linked3.o) $(<:.o=.linked2.o) 144 $(Q)diff $(<:.o=.linked2.o) $(<:.o=.linked3.o) 145 $(Q)$(BPFTOOL) gen skeleton $(<:.o=.linked3.o) name $(subst .bpf.skel.h,,$(sched)) > $@ 146 $(Q)$(BPFTOOL) gen subskeleton $(<:.o=.linked3.o) name $(subst .bpf.skel.h,,$(sched)) > $(@:.skel.h=.subskel.h) 147 148################ 149# C schedulers # 150################ 151 152override define CLEAN 153 rm -rf $(OUTPUT_DIR) 154 rm -f $(TEST_GEN_PROGS) 155endef 156 157# Every testcase takes all of the BPF progs are dependencies by default. This 158# allows testcases to load any BPF scheduler, which is useful for testcases 159# that don't need their own prog to run their test. 160all_test_bpfprogs := $(foreach prog,$(wildcard *.bpf.c),$(INCLUDE_DIR)/$(patsubst %.c,%.skel.h,$(prog))) 161 162auto-test-targets := \ 163 create_dsq \ 164 enq_last_no_enq_fails \ 165 enq_select_cpu_fails \ 166 ddsp_bogus_dsq_fail \ 167 ddsp_vtimelocal_fail \ 168 dsp_local_on \ 169 exit \ 170 hotplug \ 171 init_enable_count \ 172 maximal \ 173 maybe_null \ 174 minimal \ 175 prog_run \ 176 reload_loop \ 177 select_cpu_dfl \ 178 select_cpu_dfl_nodispatch \ 179 select_cpu_dispatch \ 180 select_cpu_dispatch_bad_dsq \ 181 select_cpu_dispatch_dbl_dsp \ 182 select_cpu_vtime \ 183 test_example \ 184 185testcase-targets := $(addsuffix .o,$(addprefix $(SCXOBJ_DIR)/,$(auto-test-targets))) 186 187$(SCXOBJ_DIR)/runner.o: runner.c | $(SCXOBJ_DIR) $(BPFOBJ) 188 $(CC) $(CFLAGS) -c $< -o $@ 189 190# Create all of the test targets object files, whose testcase objects will be 191# registered into the runner in ELF constructors. 192# 193# Note that we must do double expansion here in order to support conditionally 194# compiling BPF object files only if one is present, as the wildcard Make 195# function doesn't support using implicit rules otherwise. 196$(testcase-targets): $(SCXOBJ_DIR)/%.o: %.c $(SCXOBJ_DIR)/runner.o $(all_test_bpfprogs) | $(SCXOBJ_DIR) 197 $(eval test=$(patsubst %.o,%.c,$(notdir $@))) 198 $(CC) $(CFLAGS) -c $< -o $@ 199 200$(SCXOBJ_DIR)/util.o: util.c | $(SCXOBJ_DIR) 201 $(CC) $(CFLAGS) -c $< -o $@ 202 203$(OUTPUT)/runner: $(SCXOBJ_DIR)/runner.o $(SCXOBJ_DIR)/util.o $(BPFOBJ) $(testcase-targets) 204 @echo "$(testcase-targets)" 205 $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) 206 207.DEFAULT_GOAL := all 208 209.DELETE_ON_ERROR: 210 211.SECONDARY: 212