11# Copyright (c) The mlkem-native project authors
22# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
33
4+ # Zephyr test platform for QEMU-emulated Arm MPS boards.
5+ #
6+ # Each test binary is built as a Zephyr application by CMake (which owns the arm
7+ # toolchain, per-board arch flags and libc via the .#zephyr dev shell). The
8+ # generic rules don't link these; CUSTOM_BUILD (below, see test/mk/rules.mk)
9+ # drives the CMake build from the binary's TEST_SRCS, set by components.mk --
10+ # adding a test binary there needs no change here.
11+
412PLATFORM_PATH := test/zephyr
513
614# BUILD_DIR is set by the top-level Makefile after this file is included;
7- # define it here too so the explicit bin rules below expand to the right path.
15+ # define it here too so CUSTOM_BUILD below expands to the right path.
816BUILD_DIR ?= test/build
917
1018# ZEPHYR_TARGET=<key> selects a target. Each key maps to a Zephyr board and the
1119# QEMU machine emulating it; add a board with a row below.
1220ZEPHYR_TARGET ?= mps3-an547
1321
1422ZEPHYR_BOARD_mps2-an385 := mps2/an385
15- ZEPHYR_QEMU_mps2-an385 := mps2-an385 # Cortex-M3
23+ ZEPHYR_QEMU_mps2-an385 := mps2-an385 # Cortex-M3
1624ZEPHYR_BOARD_mps2-an386 := mps2/an386
17- ZEPHYR_QEMU_mps2-an386 := mps2-an386 # Cortex-M4
25+ ZEPHYR_QEMU_mps2-an386 := mps2-an386 # Cortex-M4
1826ZEPHYR_BOARD_mps2-an500 := mps2/an500
19- ZEPHYR_QEMU_mps2-an500 := mps2-an500 # Cortex-M7
27+ ZEPHYR_QEMU_mps2-an500 := mps2-an500 # Cortex-M7
2028ZEPHYR_BOARD_mps2-an521 := mps2/an521/cpu0
21- ZEPHYR_QEMU_mps2-an521 := mps2-an521 # Cortex-M33
29+ ZEPHYR_QEMU_mps2-an521 := mps2-an521 # Cortex-M33
2230ZEPHYR_BOARD_mps3-an547 := mps3/corstone300/an547
23- ZEPHYR_QEMU_mps3-an547 := mps3-an547 # Cortex-M55
31+ ZEPHYR_QEMU_mps3-an547 := mps3-an547 # Cortex-M55
2432
2533ZEPHYR_FIPS202_BACKEND_mps3-an547 := fips202/native/armv81m/mve.h
2634
@@ -33,11 +41,8 @@ ifeq ($(ZEPHYR_BOARD),)
3341$(error Unknown ZEPHYR_TARGET '$(ZEPHYR_TARGET ) '. Supported : $(ZEPHYR_TARGETS ) )
3442endif
3543
36- # The test binaries are built by Zephyr's CMake (which uses its own arm
37- # toolchain via the .#zephyr dev shell), not the generic Make rules. The
38- # top-level targets still attach the usual object/library prerequisites to the
39- # bin paths; with OPT=0 those are portable host objects that compile cleanly
40- # and are simply discarded (the Zephyr ELF is copied over them).
44+ # CUSTOM_BUILD must be set before components.mk is included so it switches that
45+ # file to source prerequisites (it is: the top-level Makefile includes us first).
4146OPT ?= 0
4247
4348# Native backends are an OPT=1 feature (an547 builds the Armv8.1-M MVE backend).
@@ -46,51 +51,41 @@ ZEPHYR_FIPS202_BACKEND := $(if $(filter 1,$(OPT)),$(strip $(ZEPHYR_FIPS202_BACKE
4651ZEPHYR_APP := $(PLATFORM_PATH ) /app
4752ZEPHYR_BUILD_DIR := $(BUILD_DIR ) /zephyr/$(ZEPHYR_TARGET )
4853
49- # Build a test as a Zephyr application and drop the resulting ELF at the path
50- # the top-level Makefile expects. An explicit rule for the exact bin path wins
51- # over the generic link pattern rule in test/mk/rules.mk.
52- # $(1) level $(2) bin name $(3) test source (repo-relative) $(4) extra -D
53- define ZEPHYR_BIN
54- $(BUILD_DIR ) /mlkem$(1 ) /bin/$(2 ) :
55- $$(Q ) echo " ZEPHYR $(ZEPHYR_TARGET ) ML-KEM-$(1 ) : $(3 ) "
56- $$(Q ) cmake -GNinja -S $(ZEPHYR_APP ) -B $(ZEPHYR_BUILD_DIR ) /$(2 ) \
54+ # Per-binary CMake build dir, keyed on $(notdir $@) so binaries build in
55+ # parallel. Recipe-expanded, so $@ is the specific bin being built.
56+ ZEPHYR_OUT = $(ZEPHYR_BUILD_DIR ) /$(notdir $@ )
57+
58+ # Shrink the test iteration counts (the sources default them higher, sized for
59+ # native hardware): QEMU is far slower. On CFLAGS so they forward below.
60+ CFLAGS += -DNTESTS_FUNC=3 -DNTESTS_KAT=100 \
61+ -DMLK_BENCHMARK_NTESTS=10 -DMLK_BENCHMARK_NITERATIONS=10 -DMLK_BENCHMARK_NWARMUP=10 \
62+ -DNUM_RANDOM_TESTS=100 -DNUM_RANDOM_TESTS_REJ_UNIFORM=100 -DMAX_INTT_CONSTANT_COEFF=512
63+
64+ # The binary's CFLAGS, forwarded to the CMake build (which applies them to the
65+ # mlkem amalgamation and test sources alike). '=' not ':=', so the recipe-time
66+ # $(CFLAGS) includes the binary's target-specific additions (e.g.
67+ # -DMLK_STATIC_TESTABLE= for test_unit, -DMLK_CONFIG_FILE="..." for test_alloc).
68+ # Two rewrites:
69+ # - -Imlkem -> absolute, as CMake builds from its own dir, not the repo root
70+ # (and the alloc config path is relative to -Imlkem);
71+ # - \" -> \\", so one level of quoting survives each of the recipe shell and
72+ # CMake's separate_arguments and reaches the compiler intact.
73+ # Requires AUTO=0 (see .github/workflows/zephyr.yml): the host-arch flags AUTO=1
74+ # adds must not reach the Zephyr toolchain, which selects the target arch itself.
75+ ZEPHYR_TEST_CFLAGS = $(subst \",\\\",$(patsubst -Imlkem,-I$(abspath mlkem) ,$(CFLAGS ) ) )
76+
77+ CUSTOM_BUILD = \
78+ echo " ZEPHYR $(ZEPHYR_TARGET ) : $(notdir $@ ) " && \
79+ cmake -GNinja -S $(ZEPHYR_APP ) -B $(ZEPHYR_OUT ) \
5780 -DBOARD=$(ZEPHYR_BOARD ) \
5881 -DZEPHYR_NATIVE_ROOT=$(CURDIR ) \
59- -DZEPHYR_LEVEL=$(1 ) \
60- -DZEPHYR_TEST_SRC=$(3 ) \
61- -DZEPHYR_TEST_DEFS="NTESTS_FUNC=3 NTESTS_KAT=100 MLK_BENCHMARK_NTESTS=10 MLK_BENCHMARK_NITERATIONS=10 MLK_BENCHMARK_NWARMUP=10" \
82+ -DZEPHYR_TEST_SRCS="$(strip $(TEST_SRCS ) ) " \
83+ -DZEPHYR_TEST_CFLAGS="$(ZEPHYR_TEST_CFLAGS ) " \
6284 -DZEPHYR_FIPS202_BACKEND=$(ZEPHYR_FIPS202_BACKEND ) \
6385 $(if $(ZEPHYR_FIPS202_BACKEND ) ,-DCONFIG_FIPS202_MVE_BACKEND=y) \
64- $(4 ) \
65- -DUSER_CACHE_DIR=$(abspath $(ZEPHYR_BUILD_DIR ) /$(2 ) /.cache) \
66- >/dev/null
67- $$(Q ) cmake --build $(ZEPHYR_BUILD_DIR ) /$(2 ) >/dev/null
68- $$(Q ) [ -d $$(@D ) ] || mkdir -p $$(@D )
69- $$(Q ) cp $(ZEPHYR_BUILD_DIR ) /$(2 ) /zephyr/zephyr.elf $$@
70- endef
71-
72- $(eval $(call ZEPHYR_BIN,512,test_mlkem512,test/src/test_mlkem.c))
73- $(eval $(call ZEPHYR_BIN,768,test_mlkem768,test/src/test_mlkem.c))
74- $(eval $(call ZEPHYR_BIN,1024,test_mlkem1024,test/src/test_mlkem.c))
75-
76- $(eval $(call ZEPHYR_BIN,512,gen_KAT512,test/src/gen_KAT.c))
77- $(eval $(call ZEPHYR_BIN,768,gen_KAT768,test/src/gen_KAT.c))
78- $(eval $(call ZEPHYR_BIN,1024,gen_KAT1024,test/src/gen_KAT.c))
79-
80- $(eval $(call ZEPHYR_BIN,512,acvp_mlkem512,test/acvp/acvp_mlkem.c))
81- $(eval $(call ZEPHYR_BIN,768,acvp_mlkem768,test/acvp/acvp_mlkem.c))
82- $(eval $(call ZEPHYR_BIN,1024,acvp_mlkem1024,test/acvp/acvp_mlkem.c))
83-
84- $(eval $(call ZEPHYR_BIN,512,wycheproof_mlkem512,test/wycheproof/wycheproof_mlkem.c))
85- $(eval $(call ZEPHYR_BIN,768,wycheproof_mlkem768,test/wycheproof/wycheproof_mlkem.c))
86- $(eval $(call ZEPHYR_BIN,1024,wycheproof_mlkem1024,test/wycheproof/wycheproof_mlkem.c))
87-
88- $(eval $(call ZEPHYR_BIN,512,bench_mlkem512,test/bench/bench_mlkem.c,-DZEPHYR_TEST_HAL=ON))
89- $(eval $(call ZEPHYR_BIN,768,bench_mlkem768,test/bench/bench_mlkem.c,-DZEPHYR_TEST_HAL=ON))
90- $(eval $(call ZEPHYR_BIN,1024,bench_mlkem1024,test/bench/bench_mlkem.c,-DZEPHYR_TEST_HAL=ON))
91-
92- $(eval $(call ZEPHYR_BIN,512,bench_components_mlkem512,test/bench/bench_components_mlkem.c,-DZEPHYR_TEST_HAL=ON))
93- $(eval $(call ZEPHYR_BIN,768,bench_components_mlkem768,test/bench/bench_components_mlkem.c,-DZEPHYR_TEST_HAL=ON))
94- $(eval $(call ZEPHYR_BIN,1024,bench_components_mlkem1024,test/bench/bench_components_mlkem.c,-DZEPHYR_TEST_HAL=ON))
86+ -DUSER_CACHE_DIR=$(abspath $(ZEPHYR_OUT ) /.cache) \
87+ >/dev/null && \
88+ cmake --build $(ZEPHYR_OUT ) >/dev/null && \
89+ cp $(ZEPHYR_OUT ) /zephyr/zephyr.elf $@
9590
9691EXEC_WRAPPER := $(abspath $(PLATFORM_PATH ) /exec_wrapper.py)
0 commit comments