162306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci# Makefile for nolibc tests
362306a36Sopenharmony_ciinclude ../../../scripts/Makefile.include
462306a36Sopenharmony_ci# We need this for the "cc-option" macro.
562306a36Sopenharmony_ciinclude ../../../build/Build.include
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci# we're in ".../tools/testing/selftests/nolibc"
862306a36Sopenharmony_ciifeq ($(srctree),)
962306a36Sopenharmony_cisrctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR)))
1062306a36Sopenharmony_ciendif
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciifeq ($(ARCH),)
1362306a36Sopenharmony_ciinclude $(srctree)/scripts/subarch.include
1462306a36Sopenharmony_ciARCH = $(SUBARCH)
1562306a36Sopenharmony_ciendif
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci# XARCH extends the kernel's ARCH with a few variants of the same
1862306a36Sopenharmony_ci# architecture that only differ by the configuration, the toolchain
1962306a36Sopenharmony_ci# and the Qemu program used. It is copied as-is into ARCH except for
2062306a36Sopenharmony_ci# a few specific values which are mapped like this:
2162306a36Sopenharmony_ci#
2262306a36Sopenharmony_ci#  XARCH        | ARCH      | config
2362306a36Sopenharmony_ci#  -------------|-----------|-------------------------
2462306a36Sopenharmony_ci#  ppc          | powerpc   | 32 bits
2562306a36Sopenharmony_ci#  ppc64        | powerpc   | 64 bits big endian
2662306a36Sopenharmony_ci#  ppc64le      | powerpc   | 64 bits little endian
2762306a36Sopenharmony_ci#
2862306a36Sopenharmony_ci# It is recommended to only use XARCH, though it does not harm if
2962306a36Sopenharmony_ci# ARCH is already set. For simplicity, ARCH is sufficient for all
3062306a36Sopenharmony_ci# architectures where both are equal.
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci# configure default variants for target kernel supported architectures
3362306a36Sopenharmony_ciXARCH_powerpc    = ppc
3462306a36Sopenharmony_ciXARCH            = $(or $(XARCH_$(ARCH)),$(ARCH))
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci# map from user input variants to their kernel supported architectures
3762306a36Sopenharmony_ciARCH_ppc         = powerpc
3862306a36Sopenharmony_ciARCH_ppc64       = powerpc
3962306a36Sopenharmony_ciARCH_ppc64le     = powerpc
4062306a36Sopenharmony_ciARCH            := $(or $(ARCH_$(XARCH)),$(XARCH))
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci# kernel image names by architecture
4362306a36Sopenharmony_ciIMAGE_i386       = arch/x86/boot/bzImage
4462306a36Sopenharmony_ciIMAGE_x86_64     = arch/x86/boot/bzImage
4562306a36Sopenharmony_ciIMAGE_x86        = arch/x86/boot/bzImage
4662306a36Sopenharmony_ciIMAGE_arm64      = arch/arm64/boot/Image
4762306a36Sopenharmony_ciIMAGE_arm        = arch/arm/boot/zImage
4862306a36Sopenharmony_ciIMAGE_mips       = vmlinuz
4962306a36Sopenharmony_ciIMAGE_ppc        = vmlinux
5062306a36Sopenharmony_ciIMAGE_ppc64      = vmlinux
5162306a36Sopenharmony_ciIMAGE_ppc64le    = arch/powerpc/boot/zImage
5262306a36Sopenharmony_ciIMAGE_riscv      = arch/riscv/boot/Image
5362306a36Sopenharmony_ciIMAGE_s390       = arch/s390/boot/bzImage
5462306a36Sopenharmony_ciIMAGE_loongarch  = arch/loongarch/boot/vmlinuz.efi
5562306a36Sopenharmony_ciIMAGE            = $(IMAGE_$(XARCH))
5662306a36Sopenharmony_ciIMAGE_NAME       = $(notdir $(IMAGE))
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci# default kernel configurations that appear to be usable
5962306a36Sopenharmony_ciDEFCONFIG_i386       = defconfig
6062306a36Sopenharmony_ciDEFCONFIG_x86_64     = defconfig
6162306a36Sopenharmony_ciDEFCONFIG_x86        = defconfig
6262306a36Sopenharmony_ciDEFCONFIG_arm64      = defconfig
6362306a36Sopenharmony_ciDEFCONFIG_arm        = multi_v7_defconfig
6462306a36Sopenharmony_ciDEFCONFIG_mips       = malta_defconfig
6562306a36Sopenharmony_ciDEFCONFIG_ppc        = pmac32_defconfig
6662306a36Sopenharmony_ciDEFCONFIG_ppc64      = powernv_be_defconfig
6762306a36Sopenharmony_ciDEFCONFIG_ppc64le    = powernv_defconfig
6862306a36Sopenharmony_ciDEFCONFIG_riscv      = defconfig
6962306a36Sopenharmony_ciDEFCONFIG_s390       = defconfig
7062306a36Sopenharmony_ciDEFCONFIG_loongarch  = defconfig
7162306a36Sopenharmony_ciDEFCONFIG            = $(DEFCONFIG_$(XARCH))
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci# optional tests to run (default = all)
7462306a36Sopenharmony_ciTEST =
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci# QEMU_ARCH: arch names used by qemu
7762306a36Sopenharmony_ciQEMU_ARCH_i386       = i386
7862306a36Sopenharmony_ciQEMU_ARCH_x86_64     = x86_64
7962306a36Sopenharmony_ciQEMU_ARCH_x86        = x86_64
8062306a36Sopenharmony_ciQEMU_ARCH_arm64      = aarch64
8162306a36Sopenharmony_ciQEMU_ARCH_arm        = arm
8262306a36Sopenharmony_ciQEMU_ARCH_mips       = mipsel  # works with malta_defconfig
8362306a36Sopenharmony_ciQEMU_ARCH_ppc        = ppc
8462306a36Sopenharmony_ciQEMU_ARCH_ppc64      = ppc64
8562306a36Sopenharmony_ciQEMU_ARCH_ppc64le    = ppc64le
8662306a36Sopenharmony_ciQEMU_ARCH_riscv      = riscv64
8762306a36Sopenharmony_ciQEMU_ARCH_s390       = s390x
8862306a36Sopenharmony_ciQEMU_ARCH_loongarch  = loongarch64
8962306a36Sopenharmony_ciQEMU_ARCH            = $(QEMU_ARCH_$(XARCH))
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci# QEMU_ARGS : some arch-specific args to pass to qemu
9262306a36Sopenharmony_ciQEMU_ARGS_i386       = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
9362306a36Sopenharmony_ciQEMU_ARGS_x86_64     = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
9462306a36Sopenharmony_ciQEMU_ARGS_x86        = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
9562306a36Sopenharmony_ciQEMU_ARGS_arm64      = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
9662306a36Sopenharmony_ciQEMU_ARGS_arm        = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
9762306a36Sopenharmony_ciQEMU_ARGS_mips       = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
9862306a36Sopenharmony_ciQEMU_ARGS_ppc        = -M g3beige -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
9962306a36Sopenharmony_ciQEMU_ARGS_ppc64      = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
10062306a36Sopenharmony_ciQEMU_ARGS_ppc64le    = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
10162306a36Sopenharmony_ciQEMU_ARGS_riscv      = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
10262306a36Sopenharmony_ciQEMU_ARGS_s390       = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
10362306a36Sopenharmony_ciQEMU_ARGS_loongarch  = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
10462306a36Sopenharmony_ciQEMU_ARGS            = $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_EXTRA)
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci# OUTPUT is only set when run from the main makefile, otherwise
10762306a36Sopenharmony_ci# it defaults to this nolibc directory.
10862306a36Sopenharmony_ciOUTPUT ?= $(CURDIR)/
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ciifeq ($(V),1)
11162306a36Sopenharmony_ciQ=
11262306a36Sopenharmony_cielse
11362306a36Sopenharmony_ciQ=@
11462306a36Sopenharmony_ciendif
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ciCFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple)
11762306a36Sopenharmony_ciCFLAGS_ppc64 = -m64 -mbig-endian -mno-vsx $(call cc-option,-mmultiple)
11862306a36Sopenharmony_ciCFLAGS_ppc64le = -m64 -mlittle-endian -mno-vsx $(call cc-option,-mabi=elfv2)
11962306a36Sopenharmony_ciCFLAGS_s390 = -m64
12062306a36Sopenharmony_ciCFLAGS_mips = -EL
12162306a36Sopenharmony_ciCFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call cc-option,-fstack-protector-all))
12262306a36Sopenharmony_ciCFLAGS  ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wextra \
12362306a36Sopenharmony_ci		$(call cc-option,-fno-stack-protector) \
12462306a36Sopenharmony_ci		$(CFLAGS_$(XARCH)) $(CFLAGS_STACKPROTECTOR)
12562306a36Sopenharmony_ciLDFLAGS :=
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciREPORT  ?= awk '/\[OK\][\r]*$$/{p++} /\[FAIL\][\r]*$$/{if (!f) printf("\n"); f++; print;} /\[SKIPPED\][\r]*$$/{s++} \
12862306a36Sopenharmony_ci		END{ printf("\n%3d test(s): %3d passed, %3d skipped, %3d failed => status: ", p+s+f, p, s, f); \
12962306a36Sopenharmony_ci		if (f) printf("failure\n"); else if (s) printf("warning\n"); else printf("success\n");; \
13062306a36Sopenharmony_ci		printf("\nSee all results in %s\n", ARGV[1]); }'
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cihelp:
13362306a36Sopenharmony_ci	@echo "Supported targets under selftests/nolibc:"
13462306a36Sopenharmony_ci	@echo "  all          call the \"run\" target below"
13562306a36Sopenharmony_ci	@echo "  help         this help"
13662306a36Sopenharmony_ci	@echo "  sysroot      create the nolibc sysroot here (uses \$$ARCH)"
13762306a36Sopenharmony_ci	@echo "  nolibc-test  build the executable (uses \$$CC and \$$CROSS_COMPILE)"
13862306a36Sopenharmony_ci	@echo "  libc-test    build an executable using the compiler's default libc instead"
13962306a36Sopenharmony_ci	@echo "  run-user     runs the executable under QEMU (uses \$$XARCH, \$$TEST)"
14062306a36Sopenharmony_ci	@echo "  initramfs    prepare the initramfs with nolibc-test"
14162306a36Sopenharmony_ci	@echo "  defconfig    create a fresh new default config (uses \$$XARCH)"
14262306a36Sopenharmony_ci	@echo "  kernel       (re)build the kernel with the initramfs (uses \$$XARCH)"
14362306a36Sopenharmony_ci	@echo "  run          runs the kernel in QEMU after building it (uses \$$XARCH, \$$TEST)"
14462306a36Sopenharmony_ci	@echo "  rerun        runs a previously prebuilt kernel in QEMU (uses \$$XARCH, \$$TEST)"
14562306a36Sopenharmony_ci	@echo "  clean        clean the sysroot, initramfs, build and output files"
14662306a36Sopenharmony_ci	@echo ""
14762306a36Sopenharmony_ci	@echo "The output file is \"run.out\". Test ranges may be passed using \$$TEST."
14862306a36Sopenharmony_ci	@echo ""
14962306a36Sopenharmony_ci	@echo "Currently using the following variables:"
15062306a36Sopenharmony_ci	@echo "  ARCH          = $(ARCH)"
15162306a36Sopenharmony_ci	@echo "  XARCH         = $(XARCH)"
15262306a36Sopenharmony_ci	@echo "  CROSS_COMPILE = $(CROSS_COMPILE)"
15362306a36Sopenharmony_ci	@echo "  CC            = $(CC)"
15462306a36Sopenharmony_ci	@echo "  OUTPUT        = $(OUTPUT)"
15562306a36Sopenharmony_ci	@echo "  TEST          = $(TEST)"
15662306a36Sopenharmony_ci	@echo "  QEMU_ARCH     = $(if $(QEMU_ARCH),$(QEMU_ARCH),UNKNOWN_ARCH) [determined from \$$XARCH]"
15762306a36Sopenharmony_ci	@echo "  IMAGE_NAME    = $(if $(IMAGE_NAME),$(IMAGE_NAME),UNKNOWN_ARCH) [determined from \$$XARCH]"
15862306a36Sopenharmony_ci	@echo ""
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ciall: run
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cisysroot: sysroot/$(ARCH)/include
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cisysroot/$(ARCH)/include:
16562306a36Sopenharmony_ci	$(Q)rm -rf sysroot/$(ARCH) sysroot/sysroot
16662306a36Sopenharmony_ci	$(QUIET_MKDIR)mkdir -p sysroot
16762306a36Sopenharmony_ci	$(Q)$(MAKE) -C ../../../include/nolibc ARCH=$(ARCH) OUTPUT=$(CURDIR)/sysroot/ headers_standalone
16862306a36Sopenharmony_ci	$(Q)mv sysroot/sysroot sysroot/$(ARCH)
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ciifneq ($(NOLIBC_SYSROOT),0)
17162306a36Sopenharmony_cinolibc-test: nolibc-test.c sysroot/$(ARCH)/include
17262306a36Sopenharmony_ci	$(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \
17362306a36Sopenharmony_ci	  -nostdlib -static -Isysroot/$(ARCH)/include $< -lgcc
17462306a36Sopenharmony_cielse
17562306a36Sopenharmony_cinolibc-test: nolibc-test.c
17662306a36Sopenharmony_ci	$(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \
17762306a36Sopenharmony_ci	  -nostdlib -static -include ../../../include/nolibc/nolibc.h $< -lgcc
17862306a36Sopenharmony_ciendif
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cilibc-test: nolibc-test.c
18162306a36Sopenharmony_ci	$(QUIET_CC)$(HOSTCC) -o $@ $<
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci# local libc-test
18462306a36Sopenharmony_cirun-libc-test: libc-test
18562306a36Sopenharmony_ci	$(Q)./libc-test > "$(CURDIR)/run.out" || :
18662306a36Sopenharmony_ci	$(Q)$(REPORT) $(CURDIR)/run.out
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci# local nolibc-test
18962306a36Sopenharmony_cirun-nolibc-test: nolibc-test
19062306a36Sopenharmony_ci	$(Q)./nolibc-test > "$(CURDIR)/run.out" || :
19162306a36Sopenharmony_ci	$(Q)$(REPORT) $(CURDIR)/run.out
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci# qemu user-land test
19462306a36Sopenharmony_cirun-user: nolibc-test
19562306a36Sopenharmony_ci	$(Q)qemu-$(QEMU_ARCH) ./nolibc-test > "$(CURDIR)/run.out" || :
19662306a36Sopenharmony_ci	$(Q)$(REPORT) $(CURDIR)/run.out
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ciinitramfs: nolibc-test
19962306a36Sopenharmony_ci	$(QUIET_MKDIR)mkdir -p initramfs
20062306a36Sopenharmony_ci	$(call QUIET_INSTALL, initramfs/init)
20162306a36Sopenharmony_ci	$(Q)cp nolibc-test initramfs/init
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_cidefconfig:
20462306a36Sopenharmony_ci	$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) mrproper $(DEFCONFIG) prepare
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cikernel: initramfs
20762306a36Sopenharmony_ci	$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) CONFIG_INITRAMFS_SOURCE=$(CURDIR)/initramfs
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci# run the tests after building the kernel
21062306a36Sopenharmony_cirun: kernel
21162306a36Sopenharmony_ci	$(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(srctree)/$(IMAGE)" -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out"
21262306a36Sopenharmony_ci	$(Q)$(REPORT) $(CURDIR)/run.out
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci# re-run the tests from an existing kernel
21562306a36Sopenharmony_cirerun:
21662306a36Sopenharmony_ci	$(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(srctree)/$(IMAGE)" -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out"
21762306a36Sopenharmony_ci	$(Q)$(REPORT) $(CURDIR)/run.out
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci# report with existing test log
22062306a36Sopenharmony_cireport:
22162306a36Sopenharmony_ci	$(Q)$(REPORT) $(CURDIR)/run.out
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ciclean:
22462306a36Sopenharmony_ci	$(call QUIET_CLEAN, sysroot)
22562306a36Sopenharmony_ci	$(Q)rm -rf sysroot
22662306a36Sopenharmony_ci	$(call QUIET_CLEAN, nolibc-test)
22762306a36Sopenharmony_ci	$(Q)rm -f nolibc-test
22862306a36Sopenharmony_ci	$(call QUIET_CLEAN, libc-test)
22962306a36Sopenharmony_ci	$(Q)rm -f libc-test
23062306a36Sopenharmony_ci	$(call QUIET_CLEAN, initramfs)
23162306a36Sopenharmony_ci	$(Q)rm -rf initramfs
23262306a36Sopenharmony_ci	$(call QUIET_CLEAN, run.out)
23362306a36Sopenharmony_ci	$(Q)rm -rf run.out
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci.PHONY: sysroot/$(ARCH)/include
236