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 -Wno-microsoft-anon-tag \ 97 -fms-extensions \ 98 -O2 -mcpu=v3 99 100# sort removes libbpf duplicates when not cross-building 101MAKE_DIRS := $(sort $(OBJ_DIR)/libbpf $(OBJ_DIR)/libbpf \ 102 $(OBJ_DIR)/bpftool $(OBJ_DIR)/resolve_btfids \ 103 $(HOST_OBJ_DIR) $(INCLUDE_DIR) $(SCXOBJ_DIR)) 104 105$(MAKE_DIRS): 106 $(call msg,MKDIR,,$@) 107 $(Q)mkdir -p $@ 108 109$(BPFOBJ): $(wildcard $(BPFDIR)/*.[ch] $(BPFDIR)/Makefile) \ 110 $(APIDIR)/linux/bpf.h \ 111 | $(OBJ_DIR)/libbpf 112 $(Q)$(MAKE) $(submake_extras) -C $(BPFDIR) OUTPUT=$(OBJ_DIR)/libbpf/ \ 113 ARCH=$(ARCH) CC="$(CC)" CROSS_COMPILE=$(CROSS_COMPILE) \ 114 EXTRA_CFLAGS='-g -O0 -fPIC' \ 115 DESTDIR=$(OUTPUT_DIR) prefix= all install_headers 116 117$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile) \ 118 $(LIBBPF_OUTPUT) | $(HOST_OBJ_DIR) 119 $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOLDIR) \ 120 ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) \ 121 EXTRA_CFLAGS='-g -O0' \ 122 OUTPUT=$(HOST_OBJ_DIR)/ \ 123 LIBBPF_OUTPUT=$(HOST_LIBBPF_OUTPUT) \ 124 LIBBPF_DESTDIR=$(HOST_LIBBPF_DESTDIR) \ 125 prefix= DESTDIR=$(HOST_DESTDIR) install-bin 126 127$(INCLUDE_DIR)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR) 128ifeq ($(VMLINUX_H),) 129 $(call msg,GEN,,$@) 130 $(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@ 131else 132 $(call msg,CP,,$@) 133 $(Q)cp "$(VMLINUX_H)" $@ 134endif 135 136$(SCXOBJ_DIR)/%.bpf.o: %.bpf.c $(INCLUDE_DIR)/vmlinux.h | $(BPFOBJ) $(SCXOBJ_DIR) 137 $(call msg,CLNG-BPF,,$(notdir $@)) 138 $(Q)$(CLANG) $(BPF_CFLAGS) -target bpf -c $< -o $@ 139 140$(INCLUDE_DIR)/%.bpf.skel.h: $(SCXOBJ_DIR)/%.bpf.o $(INCLUDE_DIR)/vmlinux.h $(BPFTOOL) | $(INCLUDE_DIR) 141 $(eval sched=$(notdir $@)) 142 $(call msg,GEN-SKEL,,$(sched)) 143 $(Q)$(BPFTOOL) gen object $(<:.o=.linked1.o) $< 144 $(Q)$(BPFTOOL) gen object $(<:.o=.linked2.o) $(<:.o=.linked1.o) 145 $(Q)$(BPFTOOL) gen object $(<:.o=.linked3.o) $(<:.o=.linked2.o) 146 $(Q)diff $(<:.o=.linked2.o) $(<:.o=.linked3.o) 147 $(Q)$(BPFTOOL) gen skeleton $(<:.o=.linked3.o) name $(subst .bpf.skel.h,,$(sched)) > $@ 148 $(Q)$(BPFTOOL) gen subskeleton $(<:.o=.linked3.o) name $(subst .bpf.skel.h,,$(sched)) > $(@:.skel.h=.subskel.h) 149 150################ 151# C schedulers # 152################ 153 154override define CLEAN 155 rm -rf $(OUTPUT_DIR) 156 rm -f $(TEST_GEN_PROGS) 157endef 158 159# Every testcase takes all of the BPF progs are dependencies by default. This 160# allows testcases to load any BPF scheduler, which is useful for testcases 161# that don't need their own prog to run their test. 162all_test_bpfprogs := $(foreach prog,$(wildcard *.bpf.c),$(INCLUDE_DIR)/$(patsubst %.c,%.skel.h,$(prog))) 163 164auto-test-targets := \ 165 create_dsq \ 166 enq_last_no_enq_fails \ 167 ddsp_bogus_dsq_fail \ 168 ddsp_vtimelocal_fail \ 169 dsp_local_on \ 170 enq_select_cpu \ 171 exit \ 172 hotplug \ 173 init_enable_count \ 174 maximal \ 175 maybe_null \ 176 minimal \ 177 numa \ 178 allowed_cpus \ 179 peek_dsq \ 180 prog_run \ 181 reload_loop \ 182 select_cpu_dfl \ 183 select_cpu_dfl_nodispatch \ 184 select_cpu_dispatch \ 185 select_cpu_dispatch_bad_dsq \ 186 select_cpu_dispatch_dbl_dsp \ 187 select_cpu_vtime \ 188 rt_stall \ 189 test_example \ 190 total_bw \ 191 192testcase-targets := $(addsuffix .o,$(addprefix $(SCXOBJ_DIR)/,$(auto-test-targets))) 193 194$(SCXOBJ_DIR)/runner.o: runner.c | $(SCXOBJ_DIR) $(BPFOBJ) 195 $(CC) $(CFLAGS) -c $< -o $@ 196 197# Create all of the test targets object files, whose testcase objects will be 198# registered into the runner in ELF constructors. 199# 200# Note that we must do double expansion here in order to support conditionally 201# compiling BPF object files only if one is present, as the wildcard Make 202# function doesn't support using implicit rules otherwise. 203$(testcase-targets): $(SCXOBJ_DIR)/%.o: %.c $(SCXOBJ_DIR)/runner.o $(all_test_bpfprogs) | $(SCXOBJ_DIR) 204 $(eval test=$(patsubst %.o,%.c,$(notdir $@))) 205 $(CC) $(CFLAGS) -c $< -o $@ 206 207$(SCXOBJ_DIR)/util.o: util.c | $(SCXOBJ_DIR) 208 $(CC) $(CFLAGS) -c $< -o $@ 209 210$(OUTPUT)/runner: $(SCXOBJ_DIR)/runner.o $(SCXOBJ_DIR)/util.o $(BPFOBJ) $(testcase-targets) 211 @echo "$(testcase-targets)" 212 $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) 213 214.DEFAULT_GOAL := all 215 216.DELETE_ON_ERROR: 217 218.SECONDARY: 219