From 8b0710515029139025ed4d1071073244cbee4abc Mon Sep 17 00:00:00 2001 From: Brendan Moran Date: Tue, 16 Sep 2025 13:35:54 +0100 Subject: [PATCH 01/10] Add initial support for Armv8.1-m targets This commit is mostly an import from pqmx. It includes some helpers: 1. Added a new platform.mk 2. Added a nix package for pqmx files for platform support 3. Used platform.mk to override exec wrapper 4. Changed rules.mk to use LDFLAGS for linking instead of CFLAGS 5. Added an exec_wrapper.py that encodes the command-line arguments into a binary blob and then loads that into qemu in order to pass command-line arguments. Signed-off-by: Brendan Moran --- Makefile | 8 ++- flake.nix | 12 +++- nix/m55-an547-arm-none-eabi/default.nix | 44 ++++++++++++++ nix/m55-an547-arm-none-eabi/semihosting.patch | 31 ++++++++++ nix/util.nix | 2 + .../platform/m55-an547/exec_wrapper.py | 36 ++++++++++++ test/baremetal/platform/m55-an547/platform.mk | 57 +++++++++++++++++++ .../platform/m55-an547/src/cmdline.c | 34 +++++++++++ .../baremetal/platform/m55-an547/src/libfns.c | 37 ++++++++++++ test/mk/platform.mk | 9 +++ test/mk/rules.mk | 6 +- 11 files changed, 271 insertions(+), 5 deletions(-) create mode 100644 nix/m55-an547-arm-none-eabi/default.nix create mode 100644 nix/m55-an547-arm-none-eabi/semihosting.patch create mode 100755 test/baremetal/platform/m55-an547/exec_wrapper.py create mode 100644 test/baremetal/platform/m55-an547/platform.mk create mode 100644 test/baremetal/platform/m55-an547/src/cmdline.c create mode 100644 test/baremetal/platform/m55-an547/src/libfns.c create mode 100644 test/mk/platform.mk diff --git a/Makefile b/Makefile index c6aa613f..beac38dc 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,12 @@ SHELL := /bin/bash all: build +TARGET_PLATFORM ?= +SOURCES= +ifneq ($(TARGET_PLATFORM),) +include test/mk/platform.mk +endif + W := $(EXEC_WRAPPER) # Detect available SHA256 command @@ -61,7 +67,7 @@ run_func_87: func_87 run_func: run_func_44 run_func_65 run_func_87 run_acvp: acvp - python3 ./test/acvp_client.py $(if $(ACVP_VERSION),--version $(ACVP_VERSION)) + EXEC_WRAPPER="$(EXEC_WRAPPER)" python3 ./test/acvp_client.py $(if $(ACVP_VERSION),--version $(ACVP_VERSION)) func_44: $(MLDSA44_DIR)/bin/test_mldsa44 $(Q)echo " FUNC ML-DSA-44: $^" diff --git a/flake.nix b/flake.nix index 292ae06c..65adb68b 100644 --- a/flake.nix +++ b/flake.nix @@ -73,6 +73,10 @@ packages.toolchain_ppc64le = util.toolchain_ppc64le; packages.toolchain_aarch64_be = util.toolchain_aarch64_be; + # Build: Cortex-M55 (AN547) using arm-none-eabi-gcc, platform files from pqmx + packages.m55-an547 = util.m55-an547; + packages.default = config.packages.m55-an547; + devShells.default = util.mkShell { packages = builtins.attrValues { @@ -83,7 +87,13 @@ zig_0_13; } ++ pkgs.lib.optionals (!pkgs.stdenv.isDarwin) [ config.packages.valgrind_varlat ]; }; - + devShells.arm-embedded = util.mkShell { + packages = builtins.attrValues + { + inherit (config.packages) m55-an547; + inherit (pkgs) gcc-arm-embedded qemu coreutils python3; + }; + }; devShells.hol_light = util.mkShell { packages = builtins.attrValues { inherit (config.packages) hol_light s2n_bignum; diff --git a/nix/m55-an547-arm-none-eabi/default.nix b/nix/m55-an547-arm-none-eabi/default.nix new file mode 100644 index 00000000..49799990 --- /dev/null +++ b/nix/m55-an547-arm-none-eabi/default.nix @@ -0,0 +1,44 @@ +# Copyright (c) The mldsa-native project authors +# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + +{ stdenvNoCC +, fetchFromGitHub +, ... +}: + +# Builds mldsa-native for Cortex-M55 (AN547) using arm-none-eabi-gcc. +# It fetches the platform support files from slothy-optimizer/pqmx +# instead of using copies in the repository. + +stdenvNoCC.mkDerivation rec { + pname = "mldsa-native-m55-an547"; + version = "unstable-2025-09-17"; + + + # Fetch platform files from pqmx (envs/m55-an547) + src = fetchFromGitHub { + owner = "slothy-optimizer"; + repo = "pqmx"; + rev = "31d3237"; + hash = "sha256-sL3OduAqe6nDmP+jzJ9hePy9GOc3Snw0zC60C5UvplM="; + }; + + patches = [ ./semihosting.patch ]; + + buildPhase = '' + runHook preBuild + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + mkdir -p "$out"/platform/m55-an547/src/platform/ + cp -ru envs/m55-an547/src/platform/. "$out"/platform/m55-an547/src/platform/ + runHook postInstall + ''; + + meta = { + description = "Build of mldsa-native for Cortex-M55 (AN547) using arm-none-eabi-gcc"; + homepage = "https://github.com/slothy-optimizer/pqm4-mx"; + }; +} diff --git a/nix/m55-an547-arm-none-eabi/semihosting.patch b/nix/m55-an547-arm-none-eabi/semihosting.patch new file mode 100644 index 00000000..2087785c --- /dev/null +++ b/nix/m55-an547-arm-none-eabi/semihosting.patch @@ -0,0 +1,31 @@ +diff --git a/envs/m55-an547/src/platform/semihosting.c b/envs/m55-an547/src/platform/semihosting.c +index 221c5f28..08efccf7 100644 +--- a/envs/m55-an547/src/platform/semihosting.c ++++ b/envs/m55-an547/src/platform/semihosting.c +@@ -13,6 +13,9 @@ + static const uint32_t REPORT_EXCEPTION = 0x18; + static const uint32_t ApplicationExit = 0x20026; + ++uint32_t semihosting_syscall(uint32_t nr, const uint32_t arg); ++void __attribute__ ((destructor)) semihosting_exit(void); ++ + // Do a system call towards QEMU or the debugger. + uint32_t semihosting_syscall(uint32_t nr, const uint32_t arg) { + __asm__ volatile ( +@@ -30,6 +33,16 @@ static void __attribute__ ((destructor)) semihosting_exit(void) { + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); + } + ++void NMI_Handler(void); ++void HardFault_Handler(void); ++void MemManage_Handler(void); ++void BusFault_Handler(void); ++void UsageFault_Handler(void); ++void SecureFault_Handler(void); ++void SVC_Handler(void); ++void DebugMon_Handler(void); ++void PendSV_Handler(void); ++ + void NMI_Handler(void) { + puts("NMI_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); diff --git a/nix/util.nix b/nix/util.nix index 94004722..edde8eaf 100644 --- a/nix/util.nix +++ b/nix/util.nix @@ -30,6 +30,7 @@ rec { riscv64-gcc = wrap-gcc pkgs.pkgsCross.riscv64; riscv32-gcc = wrap-gcc pkgs.pkgsCross.riscv32; ppc64le-gcc = wrap-gcc pkgs.pkgsCross.powernv; + arm-embedded-gcc = wrap-gcc pkgs.armToolchain; aarch64_be-gcc = (pkgs.callPackage ./aarch64_be-none-linux-gnu-gcc.nix { }); in # NOTE: @@ -102,6 +103,7 @@ rec { hol_light' = pkgs.callPackage ./hol_light { }; s2n_bignum = pkgs.callPackage ./s2n_bignum { }; slothy = pkgs.callPackage ./slothy { }; + m55-an547 = pkgs.callPackage ./m55-an547-arm-none-eabi {}; # Helper function to build individual cross toolchains _individual_toolchain = { name, cross_compilers }: diff --git a/test/baremetal/platform/m55-an547/exec_wrapper.py b/test/baremetal/platform/m55-an547/exec_wrapper.py new file mode 100755 index 00000000..78196624 --- /dev/null +++ b/test/baremetal/platform/m55-an547/exec_wrapper.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +# Copyright (c) The mldsa-native project authors +# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + +import struct as st +import sys +import tempfile +import subprocess + +def err(msg, **kwargs): + print(msg, file=sys.stderr, **kwargs) + +binpath = sys.argv[1] +args = sys.argv[1:] +cmdline_offset = 0x70000 + +arg0_offset = cmdline_offset + 4 + len(args) * 4 + +arg_offsets = [ + sum(map(len, args[:i])) + i + arg0_offset for i in range(len(args)) +] + +binargs = st.pack(f"<{1+len(args)}I"+''.join(f'{len(a)+1}s' for a in args),len(args), *arg_offsets, *map(lambda x: x.encode("utf-8"), args)) +with open('args.bin', 'wb') as fd: + fd.write(binargs) + +qemu_cmd = f'qemu-system-arm -M mps3-an547 -semihosting -nographic -semihosting -kernel {binpath} -device loader,file=args.bin,addr=0x{cmdline_offset:x}'.split() +result = subprocess.run(qemu_cmd, encoding="utf-8", capture_output=True) +if result.returncode != 0: + err("FAIL!") + err(f"{qemu_cmd} failed with error code {result.returncode}") + err(result.stderr) + exit(1) + +for line in result.stdout.splitlines(): + print(line) diff --git a/test/baremetal/platform/m55-an547/platform.mk b/test/baremetal/platform/m55-an547/platform.mk new file mode 100644 index 00000000..4f97e5e9 --- /dev/null +++ b/test/baremetal/platform/m55-an547/platform.mk @@ -0,0 +1,57 @@ +# Copyright (c) The mldsa-native project authors +# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + +HAL_SRC_DIR=$(PLATFORM_PATH)/src +HAL_INC_DIR=$(PLATFORM_PATH)/inc + +CROSS_PREFIX=arm-none-eabi- +CC=gcc + +CFLAGS += \ + -O3 \ + -Wall -Wextra -Wshadow \ + -fno-common \ + -ffunction-sections \ + -fdata-sections \ + --sysroot=$(SYSROOT) \ + -DDEVICE=\"an547\" \ + -I$(HAL_INC_DIR) \ + -DARMCM55 \ + +ARCH_FLAGS += \ + -march=armv8.1-m.main+mve.fp \ + -mcpu=cortex-m55 \ + -mthumb \ + -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ + +CFLAGS += \ + $(ARCH_FLAGS) \ + --specs=nosys.specs \ + -g \ + +CFLAGS += $(CFLAGS_EXTRA) + +LDSCRIPT = $(HAL_SRC_DIR)/platform/mps3.ld + +LDFLAGS += \ + -Wl,--gc-sections \ + -L. + +LDFLAGS += \ + --specs=nosys.specs \ + -Wl,--wrap=_open \ + -Wl,--wrap=_close \ + -Wl,--wrap=_read \ + -Wl,--wrap=_write \ + -Wl,--wrap=_fstat \ + -Wl,--wrap=_getpid \ + -Wl,--wrap=_isatty \ + -Wl,--wrap=_kill \ + -Wl,--wrap=_lseek \ + -Wl,--wrap=main \ + -ffreestanding \ + -T$(LDSCRIPT) \ + $(ARCH_FLAGS) + +SOURCES += $(wildcard $(HAL_SRC_DIR)/*.c) $(wildcard $(HAL_SRC_DIR)/*/*.c) +EXEC_WRAPPER := $(PLATFORM_PATH)/exec_wrapper.py \ No newline at end of file diff --git a/test/baremetal/platform/m55-an547/src/cmdline.c b/test/baremetal/platform/m55-an547/src/cmdline.c new file mode 100644 index 00000000..ff85d921 --- /dev/null +++ b/test/baremetal/platform/m55-an547/src/cmdline.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) The mldsa-native project authors + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + */ +#include +#include +#include "ARMCM55.h" + +typedef struct cmdline_s{ + int argc; + char *argv[]; +} cmdline_t; + +#define CMDLINE_ADDR ((cmdline_t *)0x70000) + +/* Provide a prototype for the real main that the C library expects. */ +extern int __real_main(int argc, char *argv[]); +int __wrap_main(int unused_argc, char *unused_argv[]); + +#ifdef SEMIHOSTING +extern void initialise_monitor_handles(void); +#endif + +/* Wrap main: build argc/argv from cmdline and forward to __real_main. */ +int __wrap_main(int unused_argc, char *unused_argv[]) { + (void)unused_argc; + (void)unused_argv; +#ifdef SEMIHOSTING + initialise_monitor_handles(); +#endif + cmdline_t *cmdline = (cmdline_t *)CMDLINE_ADDR; + return __real_main(cmdline->argc, cmdline->argv); +} + diff --git a/test/baremetal/platform/m55-an547/src/libfns.c b/test/baremetal/platform/m55-an547/src/libfns.c new file mode 100644 index 00000000..cfc13c6d --- /dev/null +++ b/test/baremetal/platform/m55-an547/src/libfns.c @@ -0,0 +1,37 @@ +int __wrap__close(int fd); +int __wrap__fstat(int fd, struct stat *buf); +int __wrap__getpid(void); +int __wrap__isatty(void); +int __wrap__lseek(void); +int __wrap__kill(void); + + +int __wrap__close(int fd) { + (void)fd; + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); + return 0; +} + +int __wrap__fstat(int fd, struct stat *buf) { + (void)fd; + (void) buf; + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); + return 0; +} + +int __wrap__getpid(){ + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); + return 0; +} +int __wrap__isatty(){ + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); + return 0; +} +int __wrap__lseek(){ + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); + return 0; +} +int __wrap__kill(){ + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); + return 0; +} diff --git a/test/mk/platform.mk b/test/mk/platform.mk new file mode 100644 index 00000000..39b0674c --- /dev/null +++ b/test/mk/platform.mk @@ -0,0 +1,9 @@ +# Copyright (c) The mldsa-native project authors +# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + +ifeq ($(TARGET_PLATFORM),m55-an547) +PLATFORM_PATH:=test/baremetal/platform/m55-an547 +include $(PLATFORM_PATH)/platform.mk +else +$(error Platform "$(TARGET_PLATFORM)" not supported) +endif \ No newline at end of file diff --git a/test/mk/rules.mk b/test/mk/rules.mk index 67f05fc8..88dd1d1d 100644 --- a/test/mk/rules.mk +++ b/test/mk/rules.mk @@ -5,17 +5,17 @@ $(BUILD_DIR)/mldsa44/bin/%: $(CONFIG) $(Q)echo " LD $@" $(Q)[ -d $(@D) ] || mkdir -p $(@D) - $(Q)$(LD) $(CFLAGS) -o $@ $(filter %.o,$^) $(LDLIBS) + $(Q)$(LD) $(LDFLAGS) -o $@ $(filter %.o,$^) $(LDLIBS) $(BUILD_DIR)/mldsa65/bin/%: $(CONFIG) $(Q)echo " LD $@" $(Q)[ -d $(@D) ] || mkdir -p $(@D) - $(Q)$(LD) $(CFLAGS) -o $@ $(filter %.o,$^) $(LDLIBS) + $(Q)$(LD) $(LDFLAGS) -o $@ $(filter %.o,$^) $(LDLIBS) $(BUILD_DIR)/mldsa87/bin/%: $(CONFIG) $(Q)echo " LD $@" $(Q)[ -d $(@D) ] || mkdir -p $(@D) - $(Q)$(LD) $(CFLAGS) -o $@ $(filter %.o,$^) $(LDLIBS) + $(Q)$(LD) $(LDFLAGS) -o $@ $(filter %.o,$^) $(LDLIBS) $(BUILD_DIR)/%.a: $(CONFIG) $(Q)echo " AR $@" From fdcc353d7669d50b44c26c4e92cd00ccc243a4f6 Mon Sep 17 00:00:00 2001 From: Brendan Moran Date: Mon, 22 Sep 2025 17:41:23 +0100 Subject: [PATCH 02/10] fix linting errors Signed-off-by: Brendan Moran --- flake.nix | 4 +-- nix/m55-an547-arm-none-eabi/semihosting.patch | 2 ++ nix/util.nix | 2 +- .../platform/m55-an547/exec_wrapper.py | 17 +++++++----- test/baremetal/platform/m55-an547/platform.mk | 2 +- .../platform/m55-an547/src/cmdline.c | 27 ++++++++++--------- .../baremetal/platform/m55-an547/src/libfns.c | 25 ++++++++++++----- test/mk/platform.mk | 2 +- 8 files changed, 50 insertions(+), 31 deletions(-) diff --git a/flake.nix b/flake.nix index 65adb68b..6ba8aadb 100644 --- a/flake.nix +++ b/flake.nix @@ -90,8 +90,8 @@ devShells.arm-embedded = util.mkShell { packages = builtins.attrValues { - inherit (config.packages) m55-an547; - inherit (pkgs) gcc-arm-embedded qemu coreutils python3; + inherit (config.packages) m55-an547; + inherit (pkgs) gcc-arm-embedded qemu coreutils python3; }; }; devShells.hol_light = util.mkShell { diff --git a/nix/m55-an547-arm-none-eabi/semihosting.patch b/nix/m55-an547-arm-none-eabi/semihosting.patch index 2087785c..349f8064 100644 --- a/nix/m55-an547-arm-none-eabi/semihosting.patch +++ b/nix/m55-an547-arm-none-eabi/semihosting.patch @@ -1,3 +1,5 @@ +# Copyright (c) The mldsa-native project authors +# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT diff --git a/envs/m55-an547/src/platform/semihosting.c b/envs/m55-an547/src/platform/semihosting.c index 221c5f28..08efccf7 100644 --- a/envs/m55-an547/src/platform/semihosting.c diff --git a/nix/util.nix b/nix/util.nix index edde8eaf..a5353cee 100644 --- a/nix/util.nix +++ b/nix/util.nix @@ -103,7 +103,7 @@ rec { hol_light' = pkgs.callPackage ./hol_light { }; s2n_bignum = pkgs.callPackage ./s2n_bignum { }; slothy = pkgs.callPackage ./slothy { }; - m55-an547 = pkgs.callPackage ./m55-an547-arm-none-eabi {}; + m55-an547 = pkgs.callPackage ./m55-an547-arm-none-eabi { }; # Helper function to build individual cross toolchains _individual_toolchain = { name, cross_compilers }: diff --git a/test/baremetal/platform/m55-an547/exec_wrapper.py b/test/baremetal/platform/m55-an547/exec_wrapper.py index 78196624..a9905805 100755 --- a/test/baremetal/platform/m55-an547/exec_wrapper.py +++ b/test/baremetal/platform/m55-an547/exec_wrapper.py @@ -7,24 +7,29 @@ import tempfile import subprocess + def err(msg, **kwargs): print(msg, file=sys.stderr, **kwargs) + binpath = sys.argv[1] args = sys.argv[1:] cmdline_offset = 0x70000 arg0_offset = cmdline_offset + 4 + len(args) * 4 -arg_offsets = [ - sum(map(len, args[:i])) + i + arg0_offset for i in range(len(args)) -] +arg_offsets = [sum(map(len, args[:i])) + i + arg0_offset for i in range(len(args))] -binargs = st.pack(f"<{1+len(args)}I"+''.join(f'{len(a)+1}s' for a in args),len(args), *arg_offsets, *map(lambda x: x.encode("utf-8"), args)) -with open('args.bin', 'wb') as fd: +binargs = st.pack( + f"<{1+len(args)}I" + "".join(f"{len(a)+1}s" for a in args), + len(args), + *arg_offsets, + *map(lambda x: x.encode("utf-8"), args), +) +with open("args.bin", "wb") as fd: fd.write(binargs) -qemu_cmd = f'qemu-system-arm -M mps3-an547 -semihosting -nographic -semihosting -kernel {binpath} -device loader,file=args.bin,addr=0x{cmdline_offset:x}'.split() +qemu_cmd = f"qemu-system-arm -M mps3-an547 -semihosting -nographic -semihosting -kernel {binpath} -device loader,file=args.bin,addr=0x{cmdline_offset:x}".split() result = subprocess.run(qemu_cmd, encoding="utf-8", capture_output=True) if result.returncode != 0: err("FAIL!") diff --git a/test/baremetal/platform/m55-an547/platform.mk b/test/baremetal/platform/m55-an547/platform.mk index 4f97e5e9..70d6ba85 100644 --- a/test/baremetal/platform/m55-an547/platform.mk +++ b/test/baremetal/platform/m55-an547/platform.mk @@ -54,4 +54,4 @@ LDFLAGS += \ $(ARCH_FLAGS) SOURCES += $(wildcard $(HAL_SRC_DIR)/*.c) $(wildcard $(HAL_SRC_DIR)/*/*.c) -EXEC_WRAPPER := $(PLATFORM_PATH)/exec_wrapper.py \ No newline at end of file +EXEC_WRAPPER := $(PLATFORM_PATH)/exec_wrapper.py diff --git a/test/baremetal/platform/m55-an547/src/cmdline.c b/test/baremetal/platform/m55-an547/src/cmdline.c index ff85d921..a8674cc6 100644 --- a/test/baremetal/platform/m55-an547/src/cmdline.c +++ b/test/baremetal/platform/m55-an547/src/cmdline.c @@ -1,17 +1,18 @@ -/* +/* * Copyright (c) The mldsa-native project authors * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT */ -#include #include +#include #include "ARMCM55.h" -typedef struct cmdline_s{ - int argc; - char *argv[]; +typedef struct cmdline_s +{ + int argc; + char *argv[]; } cmdline_t; -#define CMDLINE_ADDR ((cmdline_t *)0x70000) +#define CMDLINE_ADDR ((cmdline_t *)0x70000) /* Provide a prototype for the real main that the C library expects. */ extern int __real_main(int argc, char *argv[]); @@ -22,13 +23,13 @@ extern void initialise_monitor_handles(void); #endif /* Wrap main: build argc/argv from cmdline and forward to __real_main. */ -int __wrap_main(int unused_argc, char *unused_argv[]) { - (void)unused_argc; - (void)unused_argv; +int __wrap_main(int unused_argc, char *unused_argv[]) +{ + (void)unused_argc; + (void)unused_argv; #ifdef SEMIHOSTING - initialise_monitor_handles(); + initialise_monitor_handles(); #endif - cmdline_t *cmdline = (cmdline_t *)CMDLINE_ADDR; - return __real_main(cmdline->argc, cmdline->argv); + cmdline_t *cmdline = (cmdline_t *)CMDLINE_ADDR; + return __real_main(cmdline->argc, cmdline->argv); } - diff --git a/test/baremetal/platform/m55-an547/src/libfns.c b/test/baremetal/platform/m55-an547/src/libfns.c index cfc13c6d..a68f00da 100644 --- a/test/baremetal/platform/m55-an547/src/libfns.c +++ b/test/baremetal/platform/m55-an547/src/libfns.c @@ -1,3 +1,8 @@ +/* + * Copyright (c) The mldsa-native project authors + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + */ +#include int __wrap__close(int fd); int __wrap__fstat(int fd, struct stat *buf); int __wrap__getpid(void); @@ -6,32 +11,38 @@ int __wrap__lseek(void); int __wrap__kill(void); -int __wrap__close(int fd) { +int __wrap__close(int fd) +{ (void)fd; semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } -int __wrap__fstat(int fd, struct stat *buf) { +int __wrap__fstat(int fd, struct stat *buf) +{ (void)fd; - (void) buf; + (void)buf; semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } -int __wrap__getpid(){ +int __wrap__getpid() +{ semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } -int __wrap__isatty(){ +int __wrap__isatty() +{ semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } -int __wrap__lseek(){ +int __wrap__lseek() +{ semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } -int __wrap__kill(){ +int __wrap__kill() +{ semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } diff --git a/test/mk/platform.mk b/test/mk/platform.mk index 39b0674c..32315cb0 100644 --- a/test/mk/platform.mk +++ b/test/mk/platform.mk @@ -6,4 +6,4 @@ PLATFORM_PATH:=test/baremetal/platform/m55-an547 include $(PLATFORM_PATH)/platform.mk else $(error Platform "$(TARGET_PLATFORM)" not supported) -endif \ No newline at end of file +endif From b5385918651f51817b93f65455afaf647943fbf3 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 23 Sep 2025 09:18:40 +0800 Subject: [PATCH 03/10] small tweaks Signed-off-by: Matthias J. Kannwischer --- flake.nix | 2 +- nix/m55-an547-arm-none-eabi/default.nix | 5 ++++ nix/m55-an547-arm-none-eabi/semihosting.patch | 7 +++--- test/baremetal/platform/m55-an547/platform.mk | 12 ++++++--- .../baremetal/platform/m55-an547/src/libfns.c | 25 ++++++++++++++----- test/mk/components.mk | 6 ++--- 6 files changed, 40 insertions(+), 17 deletions(-) diff --git a/flake.nix b/flake.nix index 6ba8aadb..a3e8ffc9 100644 --- a/flake.nix +++ b/flake.nix @@ -91,7 +91,7 @@ packages = builtins.attrValues { inherit (config.packages) m55-an547; - inherit (pkgs) gcc-arm-embedded qemu coreutils python3; + inherit (pkgs) gcc-arm-embedded qemu coreutils python3 git; }; }; devShells.hol_light = util.mkShell { diff --git a/nix/m55-an547-arm-none-eabi/default.nix b/nix/m55-an547-arm-none-eabi/default.nix index 49799990..8494e522 100644 --- a/nix/m55-an547-arm-none-eabi/default.nix +++ b/nix/m55-an547-arm-none-eabi/default.nix @@ -3,6 +3,7 @@ { stdenvNoCC , fetchFromGitHub +, writeText , ... }: @@ -37,6 +38,10 @@ stdenvNoCC.mkDerivation rec { runHook postInstall ''; + setupHook = writeText "setup-hook.sh" '' + export M55_AN547_PATH="$1/platform/m55-an547/src/platform/" + ''; + meta = { description = "Build of mldsa-native for Cortex-M55 (AN547) using arm-none-eabi-gcc"; homepage = "https://github.com/slothy-optimizer/pqm4-mx"; diff --git a/nix/m55-an547-arm-none-eabi/semihosting.patch b/nix/m55-an547-arm-none-eabi/semihosting.patch index 349f8064..990bdbb6 100644 --- a/nix/m55-an547-arm-none-eabi/semihosting.patch +++ b/nix/m55-an547-arm-none-eabi/semihosting.patch @@ -4,17 +4,16 @@ diff --git a/envs/m55-an547/src/platform/semihosting.c b/envs/m55-an547/src/plat index 221c5f28..08efccf7 100644 --- a/envs/m55-an547/src/platform/semihosting.c +++ b/envs/m55-an547/src/platform/semihosting.c -@@ -13,6 +13,9 @@ +@@ -13,6 +13,8 @@ static const uint32_t REPORT_EXCEPTION = 0x18; static const uint32_t ApplicationExit = 0x20026; - + +uint32_t semihosting_syscall(uint32_t nr, const uint32_t arg); -+void __attribute__ ((destructor)) semihosting_exit(void); + // Do a system call towards QEMU or the debugger. uint32_t semihosting_syscall(uint32_t nr, const uint32_t arg) { __asm__ volatile ( -@@ -30,6 +33,16 @@ static void __attribute__ ((destructor)) semihosting_exit(void) { +@@ -30,6 +32,16 @@ static void __attribute__ ((destructor)) semihosting_exit(void) { semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); } diff --git a/test/baremetal/platform/m55-an547/platform.mk b/test/baremetal/platform/m55-an547/platform.mk index 70d6ba85..9fe40d9d 100644 --- a/test/baremetal/platform/m55-an547/platform.mk +++ b/test/baremetal/platform/m55-an547/platform.mk @@ -10,12 +10,16 @@ CC=gcc CFLAGS += \ -O3 \ -Wall -Wextra -Wshadow \ + -Wno-pedantic \ + -Wno-redundant-decls \ + -Wno-missing-prototypes \ -fno-common \ -ffunction-sections \ -fdata-sections \ --sysroot=$(SYSROOT) \ -DDEVICE=\"an547\" \ -I$(HAL_INC_DIR) \ + -I$(M55_AN547_PATH) \ -DARMCM55 \ ARCH_FLAGS += \ @@ -31,10 +35,11 @@ CFLAGS += \ CFLAGS += $(CFLAGS_EXTRA) -LDSCRIPT = $(HAL_SRC_DIR)/platform/mps3.ld +LDSCRIPT = $(M55_AN547_PATH)/mps3.ld LDFLAGS += \ -Wl,--gc-sections \ + -Wl,--no-warn-rwx-segments \ -L. LDFLAGS += \ @@ -53,5 +58,6 @@ LDFLAGS += \ -T$(LDSCRIPT) \ $(ARCH_FLAGS) -SOURCES += $(wildcard $(HAL_SRC_DIR)/*.c) $(wildcard $(HAL_SRC_DIR)/*/*.c) -EXEC_WRAPPER := $(PLATFORM_PATH)/exec_wrapper.py +# Extra sources to be included in test binaries +EXTRA_SOURCES = $(wildcard $(HAL_SRC_DIR)/*.c) $(wildcard $(M55_AN547_PATH)/*.c) + diff --git a/test/baremetal/platform/m55-an547/src/libfns.c b/test/baremetal/platform/m55-an547/src/libfns.c index a68f00da..f8e796c1 100644 --- a/test/baremetal/platform/m55-an547/src/libfns.c +++ b/test/baremetal/platform/m55-an547/src/libfns.c @@ -2,13 +2,20 @@ * Copyright (c) The mldsa-native project authors * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT */ +#include #include + +/* Semihosting definitions */ +static const uint32_t REPORT_EXCEPTION = 0x18; +static const uint32_t ApplicationExit = 0x20026; +uint32_t semihosting_syscall(uint32_t nr, const uint32_t arg); + int __wrap__close(int fd); int __wrap__fstat(int fd, struct stat *buf); int __wrap__getpid(void); -int __wrap__isatty(void); -int __wrap__lseek(void); -int __wrap__kill(void); +int __wrap__isatty(int fd); +int __wrap__lseek(int fd, int offset, int whence); +int __wrap__kill(int pid, int sig); int __wrap__close(int fd) @@ -31,18 +38,24 @@ int __wrap__getpid() semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } -int __wrap__isatty() +int __wrap__isatty(int fd) { + (void)fd; semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } -int __wrap__lseek() +int __wrap__lseek(int fd, int offset, int whence) { + (void)fd; + (void)offset; + (void)whence; semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } -int __wrap__kill() +int __wrap__kill(int pid, int sig) { + (void)pid; + (void)sig; semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); return 0; } diff --git a/test/mk/components.mk b/test/mk/components.mk index 6553f885..2abd237f 100644 --- a/test/mk/components.mk +++ b/test/mk/components.mk @@ -67,6 +67,6 @@ $(foreach scheme,mldsa44 mldsa65 mldsa87, \ ) \ ) -$(ALL_TESTS:%=$(MLDSA44_DIR)/bin/%44): $(call MAKE_OBJS, $(MLDSA44_DIR), $(wildcard test/notrandombytes/*.c)) -$(ALL_TESTS:%=$(MLDSA65_DIR)/bin/%65): $(call MAKE_OBJS, $(MLDSA65_DIR), $(wildcard test/notrandombytes/*.c)) -$(ALL_TESTS:%=$(MLDSA87_DIR)/bin/%87): $(call MAKE_OBJS, $(MLDSA87_DIR), $(wildcard test/notrandombytes/*.c)) +$(ALL_TESTS:%=$(MLDSA44_DIR)/bin/%44): $(call MAKE_OBJS, $(MLDSA44_DIR), $(wildcard test/notrandombytes/*.c) $(EXTRA_SOURCES)) +$(ALL_TESTS:%=$(MLDSA65_DIR)/bin/%65): $(call MAKE_OBJS, $(MLDSA65_DIR), $(wildcard test/notrandombytes/*.c) $(EXTRA_SOURCES)) +$(ALL_TESTS:%=$(MLDSA87_DIR)/bin/%87): $(call MAKE_OBJS, $(MLDSA87_DIR), $(wildcard test/notrandombytes/*.c) $(EXTRA_SOURCES)) From 3ede2acff730eb7def0fc5d472e8f78d048c1f5f Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 25 Sep 2025 17:07:37 +0800 Subject: [PATCH 04/10] Add AN547 (M55) CI Signed-off-by: Matthias J. Kannwischer --- .github/workflows/all.yml | 7 ++++++ .github/workflows/baremetal.yml | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 .github/workflows/baremetal.yml diff --git a/.github/workflows/all.yml b/.github/workflows/all.yml index 6d1a62f4..ac22687c 100644 --- a/.github/workflows/all.yml +++ b/.github/workflows/all.yml @@ -51,3 +51,10 @@ jobs: needs: [ base, nix ] uses: ./.github/workflows/ct-tests.yml secrets: inherit + baremetal: + name: Baremetal + permissions: + contents: 'read' + id-token: 'write' + uses: ./.github/workflows/baremetal.yml + secrets: inherit diff --git a/.github/workflows/baremetal.yml b/.github/workflows/baremetal.yml new file mode 100644 index 00000000..666974c9 --- /dev/null +++ b/.github/workflows/baremetal.yml @@ -0,0 +1,38 @@ +# Copyright (c) The mldsa-native project authors +# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + +name: Baremetal +permissions: + contents: read +on: + workflow_call: + workflow_dispatch: + +jobs: + baremetal_tests: + name: Baremetal tests (${{ matrix.target.name }}) + strategy: + fail-fast: false + matrix: + target: + - runner: ubuntu-latest + name: 'M55-AN547' + platform: m55-an547 + nix-shell: arm-embedded + runs-on: ${{ matrix.target.runner }} + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: baremetal build + test + uses: ./.github/actions/functest + env: + TARGET_PLATFORM: ${{ matrix.target.platform }} + with: + nix-shell: ${{ matrix.target.nix-shell }} + gh_token: ${{ secrets.GITHUB_TOKEN }} + exec_wrapper: ./test/baremetal/platform/${{ matrix.target.platform }}/exec_wrapper.py + opt: no_opt + func: true + kat: false + acvp: true + examples: false + stack: false From f4425394b624dca55f6caf8b1c6503e41137df48 Mon Sep 17 00:00:00 2001 From: Brendan Moran Date: Thu, 25 Sep 2025 14:29:27 +0100 Subject: [PATCH 05/10] Fix qemu error reporting Signed-off-by: Brendan Moran --- .../platform/m55-an547/exec_wrapper.py | 2 +- test/baremetal/platform/m55-an547/platform.mk | 3 ++- .../platform/m55-an547/src/cmdline.c | 22 ++++++++++++---- .../baremetal/platform/m55-an547/src/libfns.c | 25 +++++++++++-------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/test/baremetal/platform/m55-an547/exec_wrapper.py b/test/baremetal/platform/m55-an547/exec_wrapper.py index a9905805..b659a4ff 100755 --- a/test/baremetal/platform/m55-an547/exec_wrapper.py +++ b/test/baremetal/platform/m55-an547/exec_wrapper.py @@ -29,7 +29,7 @@ def err(msg, **kwargs): with open("args.bin", "wb") as fd: fd.write(binargs) -qemu_cmd = f"qemu-system-arm -M mps3-an547 -semihosting -nographic -semihosting -kernel {binpath} -device loader,file=args.bin,addr=0x{cmdline_offset:x}".split() +qemu_cmd = f"qemu-system-arm -M mps3-an547 -nographic -semihosting -kernel {binpath} -device loader,file=args.bin,addr=0x{cmdline_offset:x}".split() result = subprocess.run(qemu_cmd, encoding="utf-8", capture_output=True) if result.returncode != 0: err("FAIL!") diff --git a/test/baremetal/platform/m55-an547/platform.mk b/test/baremetal/platform/m55-an547/platform.mk index 9fe40d9d..a608d36a 100644 --- a/test/baremetal/platform/m55-an547/platform.mk +++ b/test/baremetal/platform/m55-an547/platform.mk @@ -21,6 +21,7 @@ CFLAGS += \ -I$(HAL_INC_DIR) \ -I$(M55_AN547_PATH) \ -DARMCM55 \ + -DSEMIHOSTING\ ARCH_FLAGS += \ -march=armv8.1-m.main+mve.fp \ @@ -60,4 +61,4 @@ LDFLAGS += \ # Extra sources to be included in test binaries EXTRA_SOURCES = $(wildcard $(HAL_SRC_DIR)/*.c) $(wildcard $(M55_AN547_PATH)/*.c) - +EXEC_WRAPPER := $(realpath $(PLATFORM_PATH)/exec_wrapper.py) diff --git a/test/baremetal/platform/m55-an547/src/cmdline.c b/test/baremetal/platform/m55-an547/src/cmdline.c index a8674cc6..c53889c0 100644 --- a/test/baremetal/platform/m55-an547/src/cmdline.c +++ b/test/baremetal/platform/m55-an547/src/cmdline.c @@ -19,7 +19,20 @@ extern int __real_main(int argc, char *argv[]); int __wrap_main(int unused_argc, char *unused_argv[]); #ifdef SEMIHOSTING -extern void initialise_monitor_handles(void); +#define SYS_EXIT_EXTENDED 0x20 +#define ADP_Stopped_ApplicationExit 0x20026 +extern void semihosting_syscall(int32_t opnr, int32_t param); +void semihosting_exit_with_rc(int rc); + +void semihosting_exit_with_rc(int rc) +{ + struct exit_code_s + { + int32_t reason_code; + int32_t return_code; + } s = {ADP_Stopped_ApplicationExit, rc}; + semihosting_syscall(SYS_EXIT_EXTENDED, (int32_t)(void *)&s); +} #endif /* Wrap main: build argc/argv from cmdline and forward to __real_main. */ @@ -27,9 +40,8 @@ int __wrap_main(int unused_argc, char *unused_argv[]) { (void)unused_argc; (void)unused_argv; -#ifdef SEMIHOSTING - initialise_monitor_handles(); -#endif cmdline_t *cmdline = (cmdline_t *)CMDLINE_ADDR; - return __real_main(cmdline->argc, cmdline->argv); + int rc = __real_main(cmdline->argc, cmdline->argv); + semihosting_exit_with_rc(rc); + return rc; } diff --git a/test/baremetal/platform/m55-an547/src/libfns.c b/test/baremetal/platform/m55-an547/src/libfns.c index f8e796c1..659c772b 100644 --- a/test/baremetal/platform/m55-an547/src/libfns.c +++ b/test/baremetal/platform/m55-an547/src/libfns.c @@ -2,9 +2,9 @@ * Copyright (c) The mldsa-native project authors * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT */ +#include #include #include - /* Semihosting definitions */ static const uint32_t REPORT_EXCEPTION = 0x18; static const uint32_t ApplicationExit = 0x20026; @@ -29,33 +29,36 @@ int __wrap__fstat(int fd, struct stat *buf) { (void)fd; (void)buf; - semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); - return 0; + errno = ENOSYS; + return -1; } int __wrap__getpid() { - semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); - return 0; + errno = ENOSYS; + return -1; } + int __wrap__isatty(int fd) { (void)fd; - semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); - return 0; + errno = ENOSYS; + return -1; } + int __wrap__lseek(int fd, int offset, int whence) { (void)fd; (void)offset; (void)whence; - semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); - return 0; + errno = ENOSYS; + return -1; } + int __wrap__kill(int pid, int sig) { (void)pid; (void)sig; - semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); - return 0; + errno = ENOSYS; + return -1; } From 15fea3edaa7639368b182e6a15d9ac07fdb54d9a Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 26 Sep 2025 08:59:17 +0800 Subject: [PATCH 06/10] CI: enable KAT test Signed-off-by: Matthias J. Kannwischer --- .github/workflows/baremetal.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/baremetal.yml b/.github/workflows/baremetal.yml index 666974c9..e739a8fe 100644 --- a/.github/workflows/baremetal.yml +++ b/.github/workflows/baremetal.yml @@ -29,10 +29,9 @@ jobs: with: nix-shell: ${{ matrix.target.nix-shell }} gh_token: ${{ secrets.GITHUB_TOKEN }} - exec_wrapper: ./test/baremetal/platform/${{ matrix.target.platform }}/exec_wrapper.py opt: no_opt func: true - kat: false + kat: true acvp: true examples: false stack: false From 5fd08be497b67c856e9884320ffa17924aac13ee Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 26 Sep 2025 09:19:16 +0800 Subject: [PATCH 07/10] Simplify nix flake Signed-off-by: Matthias J. Kannwischer --- Makefile | 2 +- flake.nix | 7 +++---- nix/m55-an547-arm-none-eabi/default.nix | 23 ++++++----------------- 3 files changed, 10 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index beac38dc..e90f9e4f 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,8 @@ SHELL := /bin/bash all: build +# Target platform for baremetal targets TARGET_PLATFORM ?= -SOURCES= ifneq ($(TARGET_PLATFORM),) include test/mk/platform.mk endif diff --git a/flake.nix b/flake.nix index a3e8ffc9..5c272407 100644 --- a/flake.nix +++ b/flake.nix @@ -73,10 +73,6 @@ packages.toolchain_ppc64le = util.toolchain_ppc64le; packages.toolchain_aarch64_be = util.toolchain_aarch64_be; - # Build: Cortex-M55 (AN547) using arm-none-eabi-gcc, platform files from pqmx - packages.m55-an547 = util.m55-an547; - packages.default = config.packages.m55-an547; - devShells.default = util.mkShell { packages = builtins.attrValues { @@ -87,6 +83,9 @@ zig_0_13; } ++ pkgs.lib.optionals (!pkgs.stdenv.isDarwin) [ config.packages.valgrind_varlat ]; }; + + # Build: Cortex-M55 (AN547) using arm-none-eabi-gcc, platform files from pqmx + packages.m55-an547 = util.m55-an547; devShells.arm-embedded = util.mkShell { packages = builtins.attrValues { diff --git a/nix/m55-an547-arm-none-eabi/default.nix b/nix/m55-an547-arm-none-eabi/default.nix index 8494e522..8a93f378 100644 --- a/nix/m55-an547-arm-none-eabi/default.nix +++ b/nix/m55-an547-arm-none-eabi/default.nix @@ -4,14 +4,9 @@ { stdenvNoCC , fetchFromGitHub , writeText -, ... }: -# Builds mldsa-native for Cortex-M55 (AN547) using arm-none-eabi-gcc. -# It fetches the platform support files from slothy-optimizer/pqmx -# instead of using copies in the repository. - -stdenvNoCC.mkDerivation rec { +stdenvNoCC.mkDerivation { pname = "mldsa-native-m55-an547"; version = "unstable-2025-09-17"; @@ -25,17 +20,11 @@ stdenvNoCC.mkDerivation rec { }; patches = [ ./semihosting.patch ]; - - buildPhase = '' - runHook preBuild - runHook postBuild - ''; + dontBuild = true; installPhase = '' - runHook preInstall - mkdir -p "$out"/platform/m55-an547/src/platform/ - cp -ru envs/m55-an547/src/platform/. "$out"/platform/m55-an547/src/platform/ - runHook postInstall + mkdir -p $out/platform/m55-an547/src/platform/ + cp -r envs/m55-an547/src/platform/. $out/platform/m55-an547/src/platform/ ''; setupHook = writeText "setup-hook.sh" '' @@ -43,7 +32,7 @@ stdenvNoCC.mkDerivation rec { ''; meta = { - description = "Build of mldsa-native for Cortex-M55 (AN547) using arm-none-eabi-gcc"; - homepage = "https://github.com/slothy-optimizer/pqm4-mx"; + description = "Platform files for the Cortex-M55 (AN547)"; + homepage = "https://github.com/slothy-optimizer/pqmx"; }; } From 01896d519f399058f70307a53ac63add59c34405 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 26 Sep 2025 09:31:40 +0800 Subject: [PATCH 08/10] pqmx: Remove semihosting.c patch Ported upstream in https://github.com/slothy-optimizer/pqmx/pull/92 Signed-off-by: Matthias J. Kannwischer --- nix/m55-an547-arm-none-eabi/default.nix | 7 ++-- nix/m55-an547-arm-none-eabi/semihosting.patch | 32 ------------------- 2 files changed, 3 insertions(+), 36 deletions(-) delete mode 100644 nix/m55-an547-arm-none-eabi/semihosting.patch diff --git a/nix/m55-an547-arm-none-eabi/default.nix b/nix/m55-an547-arm-none-eabi/default.nix index 8a93f378..78a4acef 100644 --- a/nix/m55-an547-arm-none-eabi/default.nix +++ b/nix/m55-an547-arm-none-eabi/default.nix @@ -8,18 +8,17 @@ stdenvNoCC.mkDerivation { pname = "mldsa-native-m55-an547"; - version = "unstable-2025-09-17"; + version = "main-2025-09-26"; # Fetch platform files from pqmx (envs/m55-an547) src = fetchFromGitHub { owner = "slothy-optimizer"; repo = "pqmx"; - rev = "31d3237"; - hash = "sha256-sL3OduAqe6nDmP+jzJ9hePy9GOc3Snw0zC60C5UvplM="; + rev = "b58247d9771c170d3f74dbd993fa7a24d48258a8"; + hash = "sha256-APqxI5FjSDlPMc7/mT5MNjFb5TLWad179BRaoz3TP8g="; }; - patches = [ ./semihosting.patch ]; dontBuild = true; installPhase = '' diff --git a/nix/m55-an547-arm-none-eabi/semihosting.patch b/nix/m55-an547-arm-none-eabi/semihosting.patch deleted file mode 100644 index 990bdbb6..00000000 --- a/nix/m55-an547-arm-none-eabi/semihosting.patch +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (c) The mldsa-native project authors -# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT -diff --git a/envs/m55-an547/src/platform/semihosting.c b/envs/m55-an547/src/platform/semihosting.c -index 221c5f28..08efccf7 100644 ---- a/envs/m55-an547/src/platform/semihosting.c -+++ b/envs/m55-an547/src/platform/semihosting.c -@@ -13,6 +13,8 @@ - static const uint32_t REPORT_EXCEPTION = 0x18; - static const uint32_t ApplicationExit = 0x20026; - -+uint32_t semihosting_syscall(uint32_t nr, const uint32_t arg); -+ - // Do a system call towards QEMU or the debugger. - uint32_t semihosting_syscall(uint32_t nr, const uint32_t arg) { - __asm__ volatile ( -@@ -30,6 +32,16 @@ static void __attribute__ ((destructor)) semihosting_exit(void) { - semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); - } - -+void NMI_Handler(void); -+void HardFault_Handler(void); -+void MemManage_Handler(void); -+void BusFault_Handler(void); -+void UsageFault_Handler(void); -+void SecureFault_Handler(void); -+void SVC_Handler(void); -+void DebugMon_Handler(void); -+void PendSV_Handler(void); -+ - void NMI_Handler(void) { - puts("NMI_Handler"); - semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); From d9fe1277c480e6cfdd64e2b11cc918a30c6d6448 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 26 Sep 2025 10:43:44 +0800 Subject: [PATCH 09/10] Add LDFLAGS to test scripts and adjust CI Signed-off-by: Matthias J. Kannwischer --- .github/actions/bench/action.yml | 5 +++++ .github/workflows/bench.yml | 19 +++++++++++++++++-- .github/workflows/bench_ec2_any.yml | 4 ++++ .github/workflows/bench_ec2_reusable.yml | 8 ++++++++ scripts/tests | 8 ++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/.github/actions/bench/action.yml b/.github/actions/bench/action.yml index 2dd30069..a5574769 100644 --- a/.github/actions/bench/action.yml +++ b/.github/actions/bench/action.yml @@ -19,6 +19,9 @@ inputs: archflags: description: ARCHFLAGS to pass to compilation default: "" + ldflags: + description: LDFLAGS to pass to compilation + default: "" opt: description: opt flag to set for tests script default: "true" @@ -77,11 +80,13 @@ runs: run: | ./scripts/tests bench -c ${{ inputs.perf }} --cross-prefix="${{ inputs.cross_prefix }}" \ --cflags="${{ inputs.cflags }} ${{ inputs.archflags }}" \ + --ldflags="${{ inputs.ldflags }}" \ --opt=$([[ ${{ inputs.opt }} == "false" ]] && echo "no_opt" || echo "opt") \ -v --output=output.json ${{ inputs.bench_extra_args }} ./scripts/tests bench --components -c ${{ inputs.perf }} --cross-prefix="${{ inputs.cross_prefix }}" \ --cflags="${{ inputs.cflags }} ${{ inputs.archflags }}" \ + --ldflags="${{ inputs.ldflags }}" \ --opt=$([[ ${{ inputs.opt }} == "false" ]] && echo "no_opt" || echo "opt") \ -v ${{ inputs.bench_extra_args }} - name: Store benchmark result diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index a9a7ff2d..0bf34ae0 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -34,6 +34,7 @@ jobs: bench_pmu: PMU archflags: -mcpu=cortex-a72 -DMLD_SYS_AARCH64_SLOW_BARREL_SHIFTER cflags: "-flto -DMLD_FORCE_AARCH64" + ldflags: "-flto" bench_extra_args: "" nix_shell: ci-bench only_no_opt: false @@ -42,6 +43,7 @@ jobs: bench_pmu: PERF archflags: "-mcpu=cortex-a76 -march=armv8.2-a" cflags: "-flto -DMLD_FORCE_AARCH64" + ldflags: "-flto" bench_extra_args: "" nix_shell: ci-bench only_no_opt: false @@ -49,7 +51,8 @@ jobs: name: Arm Cortex-A55 (Snapdragon 888) benchmarks bench_pmu: PERF archflags: "-mcpu=cortex-a55 -march=armv8.2-a" - cflags: "-flto -static -DMLD_FORCE_AARCH64" + cflags: "-flto -DMLD_FORCE_AARCH64" + ldflags: "-flto -static" bench_extra_args: -w exec-on-a55 nix_shell: ci-bench only_no_opt: false @@ -57,7 +60,8 @@ jobs: name: SpacemiT K1 8 (Banana Pi F3) benchmarks bench_pmu: PERF archflags: "-march=rv64imafdcv_zicsr_zifencei" - cflags: "-static" + cflags: "" + ldflags: "-static" bench_extra_args: -w exec-on-bpi cross_prefix: riscv64-unknown-linux-gnu- nix_shell: ci-cross-riscv64 @@ -67,6 +71,7 @@ jobs: bench_pmu: MAC archflags: "-mcpu=apple-m1 -march=armv8.4-a+sha3" cflags: "-flto" + ldflags: "-flto" bench_extra_args: "-r" nix_shell: ci-bench only_no_opt: false @@ -80,6 +85,7 @@ jobs: name: ${{ matrix.target.name }} (opt) cflags: ${{ matrix.target.cflags }} archflags: ${{ matrix.target.archflags }} + ldflags: ${{ matrix.target.ldflags }} perf: ${{ matrix.target.bench_pmu }} store_results: ${{ github.repository_owner == 'pq-code-package' && github.ref == 'refs/heads/main' }} bench_extra_args: ${{ matrix.target.bench_extra_args }} @@ -92,6 +98,7 @@ jobs: name: ${{ matrix.target.name }} (no-opt) cflags: ${{ matrix.target.cflags }} archflags: ${{ matrix.target.archflags }} + ldflags: ${{ matrix.target.ldflags }} perf: ${{ matrix.target.bench_pmu }} store_results: ${{ github.repository_owner == 'pq-code-package' && github.ref == 'refs/heads/main' }} bench_extra_args: ${{ matrix.target.bench_extra_args }} @@ -115,42 +122,49 @@ jobs: ec2_ami: ubuntu-latest (aarch64) archflags: -mcpu=cortex-a76 -march=armv8.2-a cflags: "-flto -DMLD_FORCE_AARCH64" + ldflags: "-flto" perf: PERF - name: Graviton3 ec2_instance_type: c7g.medium ec2_ami: ubuntu-latest (aarch64) archflags: -march=armv8.4-a+sha3 cflags: "-flto -DMLD_FORCE_AARCH64" + ldflags: "-flto" perf: PERF - name: Graviton4 ec2_instance_type: c8g.medium ec2_ami: ubuntu-latest (aarch64) archflags: -march=armv9-a+sha3 cflags: "-flto -DMLD_FORCE_AARCH64" + ldflags: "-flto" perf: PERF - name: AMD EPYC 4th gen (c7a) ec2_instance_type: c7a.medium ec2_ami: ubuntu-latest (x86_64) archflags: -mavx2 -mbmi2 -mpopcnt -maes -march=znver4 cflags: "-flto -DMLD_FORCE_X86_64" + ldflags: "-flto" perf: PMU - name: Intel Xeon 4th gen (c7i) ec2_instance_type: c7i.metal-24xl ec2_ami: ubuntu-latest (x86_64) archflags: -mavx2 -mbmi2 -mpopcnt -maes -march=sapphirerapids cflags: "-flto -DMLD_FORCE_X86_64" + ldflags: "-flto" perf: PMU - name: AMD EPYC 3rd gen (c6a) ec2_instance_type: c6a.large ec2_ami: ubuntu-latest (x86_64) archflags: -mavx2 -mbmi2 -mpopcnt -maes -march=znver3 cflags: "-flto -DMLD_FORCE_X86_64" + ldflags: "-flto" perf: PMU - name: Intel Xeon 3rd gen (c6i) ec2_instance_type: c6i.large ec2_ami: ubuntu-latest (x86_64) archflags: -mavx2 -mbmi2 -mpopcnt -maes -march=icelake-server cflags: "-flto -DMLD_FORCE_X86_64" + ldflags: "-flto" perf: PMU uses: ./.github/workflows/bench_ec2_reusable.yml if: github.repository_owner == 'pq-code-package' && (github.event.label.name == 'benchmark' || github.ref == 'refs/heads/main') @@ -159,6 +173,7 @@ jobs: ec2_ami: ${{ matrix.target.ec2_ami }} archflags: ${{ matrix.target.archflags }} cflags: ${{ matrix.target.cflags }} + ldflags: ${{ matrix.target.ldflags }} opt: "all" store_results: ${{ github.repository_owner == 'pq-code-package' && github.ref == 'refs/heads/main' }} # Only store optimized results name: ${{ matrix.target.name }} diff --git a/.github/workflows/bench_ec2_any.yml b/.github/workflows/bench_ec2_any.yml index 8ac90e7e..9f341e6b 100644 --- a/.github/workflows/bench_ec2_any.yml +++ b/.github/workflows/bench_ec2_any.yml @@ -32,6 +32,9 @@ on: archflags: description: Custom ARCH flags for compilation default: '' + ldflags: + description: Custom LDFLAGS for linking + default: '' opt: description: Benchmark optimized, non-optimized, or both type: choice @@ -61,6 +64,7 @@ jobs: ec2_ami_id: ${{ inputs.ec2_ami_id }} cflags: ${{ inputs.cflags }} archflags: ${{ inputs.archflags }} + ldflags: ${{ inputs.ldflags }} opt: ${{ inputs.opt }} name: ${{ inputs.name }} store_results: false diff --git a/.github/workflows/bench_ec2_reusable.yml b/.github/workflows/bench_ec2_reusable.yml index 373259ba..f5532f41 100644 --- a/.github/workflows/bench_ec2_reusable.yml +++ b/.github/workflows/bench_ec2_reusable.yml @@ -30,6 +30,10 @@ on: type: string description: Custom ARCH flags for compilation default: -mcpu=neoverse-n1 -march=armv8.2-a + ldflags: + type: string + description: Custom LDFLAGS for linking + default: "" opt: type: string description: Runs with optimized code if enabled (opt, no_opt, all) @@ -133,6 +137,7 @@ jobs: name: ${{ inputs.name }} cflags: ${{ inputs.cflags }} archflags: ${{ inputs.archflags }} + ldflags: ${{ inputs.ldflags }} opt: true perf: ${{ inputs.perf }} store_results: ${{ inputs.store_results }} @@ -145,6 +150,7 @@ jobs: name: ${{ inputs.name }} (no-opt) cflags: ${{ inputs.cflags }} archflags: ${{ inputs.archflags }} + ldflags: ${{ inputs.ldflags }} opt: false perf: ${{ inputs.perf }} store_results: ${{ inputs.store_results }} @@ -177,6 +183,7 @@ jobs: name: ${{ inputs.name }} (${{ inputs.compiler }}) cflags: ${{ inputs.cflags }} archflags: ${{ inputs.archflags }} + ldflags: ${{ inputs.ldflags }} opt: true perf: ${{ inputs.perf }} store_results: ${{ inputs.store_results }} @@ -192,6 +199,7 @@ jobs: name: ${{ inputs.name }} (${{ inputs.compiler }}) (no-opt) cflags: ${{ inputs.cflags }} archflags: ${{ inputs.archflags }} + ldflags: ${{ inputs.ldflags }} opt: false perf: ${{ inputs.perf }} store_results: ${{ inputs.store_results }} diff --git a/scripts/tests b/scripts/tests index 383d8de7..ec3f24fc 100755 --- a/scripts/tests +++ b/scripts/tests @@ -351,6 +351,9 @@ class Tests: cflags = self.args.cflags if cflags is None: cflags = "" + ldflags = self.args.ldflags + if ldflags is None: + ldflags = "" if test_type.is_example() and self.args.cross_prefix != "": cflags += " -static" @@ -358,6 +361,8 @@ class Tests: env_update = {} if cflags != "": env_update["CFLAGS"] = cflags + if ldflags != "": + env_update["LDFLAGS"] = ldflags if self.args.cross_prefix != "": env_update["CROSS_PREFIX"] = self.args.cross_prefix @@ -798,6 +803,9 @@ def cli(): common_parser.add_argument( "--cflags", help="Extra cflags to passed in (e.g. '-mcpu=cortex-a72')" ) + common_parser.add_argument( + "--ldflags", help="Extra ldflags to passed in (e.g. '-static')" + ) common_parser.add_argument( "-j", help="Number of jobs to be used for `make` invocations", From 10448f9ef7e1b6e9cb2f43b443806c3c3fb6f55e Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 26 Sep 2025 13:57:57 +0800 Subject: [PATCH 10/10] Switch from pqmx to CMSIS_5 Signed-off-by: Matthias J. Kannwischer --- flake.nix | 5 +- nix/cmsis_5/default.nix | 37 +++ nix/m55-an547-arm-none-eabi/default.nix | 37 --- nix/util.nix | 2 +- test/baremetal/platform/m55-an547/mps3.ld | 312 ++++++++++++++++++ test/baremetal/platform/m55-an547/platform.mk | 8 +- .../baremetal/platform/m55-an547/src/libfns.c | 49 +++ .../platform/m55-an547/src/semihosting.c | 105 ++++++ .../platform/m55-an547/src/startup_ARMCM55.c | 156 +++++++++ .../platform/m55-an547/src/system_ARMCM55.c | 108 ++++++ test/baremetal/platform/m55-an547/src/uart.c | 104 ++++++ test/baremetal/platform/m55-an547/src/uart.h | 35 ++ 12 files changed, 914 insertions(+), 44 deletions(-) create mode 100644 nix/cmsis_5/default.nix delete mode 100644 nix/m55-an547-arm-none-eabi/default.nix create mode 100644 test/baremetal/platform/m55-an547/mps3.ld create mode 100644 test/baremetal/platform/m55-an547/src/semihosting.c create mode 100644 test/baremetal/platform/m55-an547/src/startup_ARMCM55.c create mode 100644 test/baremetal/platform/m55-an547/src/system_ARMCM55.c create mode 100644 test/baremetal/platform/m55-an547/src/uart.c create mode 100644 test/baremetal/platform/m55-an547/src/uart.h diff --git a/flake.nix b/flake.nix index 5c272407..3fab328d 100644 --- a/flake.nix +++ b/flake.nix @@ -84,12 +84,11 @@ } ++ pkgs.lib.optionals (!pkgs.stdenv.isDarwin) [ config.packages.valgrind_varlat ]; }; - # Build: Cortex-M55 (AN547) using arm-none-eabi-gcc, platform files from pqmx - packages.m55-an547 = util.m55-an547; + packages.cmsis_5 = util.cmsis_5; devShells.arm-embedded = util.mkShell { packages = builtins.attrValues { - inherit (config.packages) m55-an547; + inherit (config.packages) cmsis_5; inherit (pkgs) gcc-arm-embedded qemu coreutils python3 git; }; }; diff --git a/nix/cmsis_5/default.nix b/nix/cmsis_5/default.nix new file mode 100644 index 00000000..fc5ce267 --- /dev/null +++ b/nix/cmsis_5/default.nix @@ -0,0 +1,37 @@ +# Copyright (c) The mldsa-native project authors +# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + +{ stdenvNoCC +, fetchFromGitHub +, writeText +}: + +stdenvNoCC.mkDerivation { + pname = "cmsis_5"; + version = "5.9.0"; + + src = fetchFromGitHub { + owner = "ARM-software"; + repo = "CMSIS_5"; + rev = "5.9.0"; + hash = "sha256-m3V5pu/ao1d7aVhlWh0lvesAXmYA5JpOVsumAi1Wioc="; + }; + + dontBuild = true; + + installPhase = '' + mkdir -p $out + cp -r Device $out/ + cp -r CMSIS $out/ + ''; + + setupHook = writeText "setup-hook.sh" '' + export CMSIS_5_PATH="$1" + ''; + + meta = { + description = "CMSIS"; + homepage = "https://github.com/ARM-software/CMSIS_5"; + license = "Apache-2.0"; + }; +} diff --git a/nix/m55-an547-arm-none-eabi/default.nix b/nix/m55-an547-arm-none-eabi/default.nix deleted file mode 100644 index 78a4acef..00000000 --- a/nix/m55-an547-arm-none-eabi/default.nix +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) The mldsa-native project authors -# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT - -{ stdenvNoCC -, fetchFromGitHub -, writeText -}: - -stdenvNoCC.mkDerivation { - pname = "mldsa-native-m55-an547"; - version = "main-2025-09-26"; - - - # Fetch platform files from pqmx (envs/m55-an547) - src = fetchFromGitHub { - owner = "slothy-optimizer"; - repo = "pqmx"; - rev = "b58247d9771c170d3f74dbd993fa7a24d48258a8"; - hash = "sha256-APqxI5FjSDlPMc7/mT5MNjFb5TLWad179BRaoz3TP8g="; - }; - - dontBuild = true; - - installPhase = '' - mkdir -p $out/platform/m55-an547/src/platform/ - cp -r envs/m55-an547/src/platform/. $out/platform/m55-an547/src/platform/ - ''; - - setupHook = writeText "setup-hook.sh" '' - export M55_AN547_PATH="$1/platform/m55-an547/src/platform/" - ''; - - meta = { - description = "Platform files for the Cortex-M55 (AN547)"; - homepage = "https://github.com/slothy-optimizer/pqmx"; - }; -} diff --git a/nix/util.nix b/nix/util.nix index a5353cee..9d25a4ef 100644 --- a/nix/util.nix +++ b/nix/util.nix @@ -103,7 +103,7 @@ rec { hol_light' = pkgs.callPackage ./hol_light { }; s2n_bignum = pkgs.callPackage ./s2n_bignum { }; slothy = pkgs.callPackage ./slothy { }; - m55-an547 = pkgs.callPackage ./m55-an547-arm-none-eabi { }; + cmsis_5 = pkgs.callPackage ./cmsis_5 { }; # Helper function to build individual cross toolchains _individual_toolchain = { name, cross_compilers }: diff --git a/test/baremetal/platform/m55-an547/mps3.ld b/test/baremetal/platform/m55-an547/mps3.ld new file mode 100644 index 00000000..7e24a897 --- /dev/null +++ b/test/baremetal/platform/m55-an547/mps3.ld @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + *-------- <<< Use Configuration Wizard in Context Menu >>> ------------------- + */ + +/*---------------------- ITCM Configuration ---------------------------------- + Flash Configuration + Flash Base Address <0x0-0xFFFFFFFF:8> + Flash Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__ROM_BASE = 0x00000000; +__ROM_SIZE = 0x00080000; + +/*--------------------- DTCM RAM Configuration ---------------------------- + RAM Configuration + RAM Base Address <0x0-0xFFFFFFFF:8> + RAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__RAM_BASE = 0x20000000; +__RAM_SIZE = 0x00080000; + +/*--------------------- Embedded SRAM Configuration ---------------------------- + SRAM Configuration + SRAM Base Address <0x0-0xFFFFFFFF:8> + SRAM Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__SRAM_BASE = 0x21000000; +__SRAM_SIZE = 0x00200000; + +/*--------------------- Stack / Heap Configuration ---------------------------- + Stack / Heap Configuration + Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> + Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__STACK_SIZE = 0x0000e000; +__HEAP_SIZE = 0x00001000; + +/*--------------------- Embedded RAM Configuration ---------------------------- + DDR Configuration + DDR Base Address <0x0-0xFFFFFFFF:8> + DDR Size (in Bytes) <0x0-0xFFFFFFFF:8> + + -----------------------------------------------------------------------------*/ +__DDR_BASE = 0x60000000; +__DDR_SIZE = 0x02000000; + +/* + *-------------------- <<< end of configuration section >>> ------------------- + */ + +MEMORY +{ + ITCM (rx) : ORIGIN = __ROM_BASE, LENGTH = __ROM_SIZE + DTCM (rwx) : ORIGIN = __RAM_BASE, LENGTH = __RAM_SIZE + SRAM (rwx) : ORIGIN = __SRAM_BASE, LENGTH = __SRAM_SIZE + DDR (rwx) : ORIGIN = __DDR_BASE, LENGTH = __DDR_SIZE +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions ITCM and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.vectors)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > ITCM + + /* + * SG veneers: + * All SG veneers are placed in the special output section .gnu.sgstubs. Its start address + * must be set, either with the command line option �--section-start� or in a linker script, + * to indicate where to place these veneers in memory. + */ +/* + .gnu.sgstubs : + { + . = ALIGN(32); + } > ITCM +*/ + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > ITCM + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ITCM + __exidx_end = .; + + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + /* Add each additional data section here */ + __copy_table_end__ = .; + } > ITCM + + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + /* Add each additional bss section here */ +/* + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) +*/ + __zero_table_end__ = .; + } > ITCM + + /** + * Location counter can end up 2byte aligned with narrow Thumb code but + * __etext is assumed by startup code to be the LMA of a section in DTCM + * which must be 4byte aligned + */ + __etext = ALIGN (4); + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data) + *(.data.*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > DTCM + + /* + * Secondary data section, optional + * + * Remember to add each additional data section + * to the .copy.table above to asure proper + * initialization during startup. + */ +/* + __etext2 = ALIGN (4); + + .data2 : AT (__etext2) + { + . = ALIGN(4); + __data2_start__ = .; + *(.data2) + *(.data2.*) + . = ALIGN(4); + __data2_end__ = .; + + } > RAM2 +*/ + + .sram : + { + . = ALIGN(16); + *(.bss.NoInit) + . = ALIGN(16); + } > DTCM AT > DTCM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > DTCM AT > DTCM + + + /* + * Secondary bss section, optional + * + * Remember to add each additional bss section + * to the .zero.table above to asure proper + * initialization during startup. + */ +/* + .bss2 : + { + . = ALIGN(4); + __bss2_start__ = .; + *(.bss2) + *(.bss2.*) + . = ALIGN(4); + __bss2_end__ = .; + } > RAM2 AT > RAM2 +*/ + + .heap (COPY) : + { + . = ALIGN(8); + __end__ = .; + PROVIDE(end = .); + . = . + __HEAP_SIZE; + . = ALIGN(8); + __HeapLimit = .; + } > DTCM + + .stack (ORIGIN(DTCM) + LENGTH(DTCM) - __STACK_SIZE) (COPY) : + { + . = ALIGN(8); + __StackLimit = .; + . = . + __STACK_SIZE; + . = ALIGN(8); + __StackTop = .; + } > DTCM + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds DTCM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region DTCM overflowed with stack") +} diff --git a/test/baremetal/platform/m55-an547/platform.mk b/test/baremetal/platform/m55-an547/platform.mk index a608d36a..6a72fb1b 100644 --- a/test/baremetal/platform/m55-an547/platform.mk +++ b/test/baremetal/platform/m55-an547/platform.mk @@ -19,7 +19,9 @@ CFLAGS += \ --sysroot=$(SYSROOT) \ -DDEVICE=\"an547\" \ -I$(HAL_INC_DIR) \ - -I$(M55_AN547_PATH) \ + -I$(HAL_SRC_DIR) \ + -I$(CMSIS_5_PATH)/CMSIS/Core/Include \ + -I$(CMSIS_5_PATH)/Device/ARM/ARMCM55/Include \ -DARMCM55 \ -DSEMIHOSTING\ @@ -36,7 +38,7 @@ CFLAGS += \ CFLAGS += $(CFLAGS_EXTRA) -LDSCRIPT = $(M55_AN547_PATH)/mps3.ld +LDSCRIPT = $(PLATFORM_PATH)/mps3.ld LDFLAGS += \ -Wl,--gc-sections \ @@ -60,5 +62,5 @@ LDFLAGS += \ $(ARCH_FLAGS) # Extra sources to be included in test binaries -EXTRA_SOURCES = $(wildcard $(HAL_SRC_DIR)/*.c) $(wildcard $(M55_AN547_PATH)/*.c) +EXTRA_SOURCES = $(wildcard $(HAL_SRC_DIR)/*.c) EXEC_WRAPPER := $(realpath $(PLATFORM_PATH)/exec_wrapper.py) diff --git a/test/baremetal/platform/m55-an547/src/libfns.c b/test/baremetal/platform/m55-an547/src/libfns.c index 659c772b..8c52c6bf 100644 --- a/test/baremetal/platform/m55-an547/src/libfns.c +++ b/test/baremetal/platform/m55-an547/src/libfns.c @@ -5,6 +5,9 @@ #include #include #include +#include "uart.h" +#undef errno +extern int errno; /* Semihosting definitions */ static const uint32_t REPORT_EXCEPTION = 0x18; static const uint32_t ApplicationExit = 0x20026; @@ -62,3 +65,49 @@ int __wrap__kill(int pid, int sig) errno = ENOSYS; return -1; } + +int __wrap__read(int file, char *ptr, int len) +{ + if (file == 0) + { + int i; + for (i = 0; i < len; ++i) + { + ptr[i] = uart_getc(); + if (ptr[i] == '\r') + { + ptr[i] = '\n'; + } + if (ptr[i] == '\n') + { + i += 1; + break; + } + } + errno = 0; + return i; + } + else + { + errno = ENOSYS; + } + return -1; +} + +int __wrap__write(int file, char *ptr, int len) +{ + if (file == 1 || file == 2) + { + for (int i = 0; i < len; ++i) + { + uart_putc(ptr[i]); + } + errno = 0; + return len; + } + else + { + errno = ENOSYS; + } + return -1; +} diff --git a/test/baremetal/platform/m55-an547/src/semihosting.c b/test/baremetal/platform/m55-an547/src/semihosting.c new file mode 100644 index 00000000..9dba4ec9 --- /dev/null +++ b/test/baremetal/platform/m55-an547/src/semihosting.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) The mldsa-native project authors + * SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT + */ + +/* + * Based on the CC0 implementation in pqm3 + * https://github.com/mupq/pqm3/blob/master/common/hal-mps2.c + */ + +#if !defined(NO_SEMIHOSTING_EXIT) + +#include +#include + +static const uint32_t REPORT_EXCEPTION = 0x18; +static const uint32_t ApplicationExit = 0x20026; + +uint32_t semihosting_syscall(uint32_t nr, const uint32_t arg); +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SecureFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); + +// Do a system call towards QEMU or the debugger. +uint32_t semihosting_syscall(uint32_t nr, const uint32_t arg) +{ + __asm__ volatile( + "mov r0, %[nr]\n" + "mov r1, %[arg]\n" + "bkpt 0xAB\n" + "mov %[nr], r0\n" + : [nr] "+r"(nr) + : [arg] "r"(arg) + : "0", "1"); + return nr; +} + +// Register a destructor that will call qemu telling them that the program +// has exited successfully. +static void __attribute__((destructor)) semihosting_exit(void) +{ + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +void NMI_Handler(void) +{ + puts("NMI_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +void HardFault_Handler(void) +{ + puts("HardFault_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +void MemManage_Handler(void) +{ + puts("MemManage_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +void BusFault_Handler(void) +{ + puts("BusFault_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +void UsageFault_Handler(void) +{ + puts("UsageFault_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +void SecureFault_Handler(void) +{ + puts("SecureFault_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +void SVC_Handler(void) +{ + puts("SVC_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +void DebugMon_Handler(void) +{ + puts("DebugMon_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +void PendSV_Handler(void) +{ + puts("PendSV_Handler"); + semihosting_syscall(REPORT_EXCEPTION, ApplicationExit); +} + +#endif /* !defined(NO_SEMIHOSTING_EXIT) */ diff --git a/test/baremetal/platform/m55-an547/src/startup_ARMCM55.c b/test/baremetal/platform/m55-an547/src/startup_ARMCM55.c new file mode 100644 index 00000000..bd9aa22a --- /dev/null +++ b/test/baremetal/platform/m55-an547/src/startup_ARMCM55.c @@ -0,0 +1,156 @@ +/****************************************************************************** + * @file startup_ARMCM55.c + * @brief CMSIS-Core Device Startup File for Cortex-M55 Device + * @version V1.1.0 + * @date 16. December 2020 + ******************************************************************************/ +/* + * Copyright (c) 2020 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(ARMCM55) +#include "ARMCM55.h" +#else +#error device not specified! +#endif + +/*---------------------------------------------------------------------------- + External References + *----------------------------------------------------------------------------*/ +extern uint32_t __INITIAL_SP; +extern uint32_t __STACK_LIMIT; +#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +extern uint32_t __STACK_SEAL; +#endif + +extern __NO_RETURN void __PROGRAM_START(void); + +/*---------------------------------------------------------------------------- + Internal References + *----------------------------------------------------------------------------*/ +__NO_RETURN void Reset_Handler(void); +void Default_Handler(void); + +/*---------------------------------------------------------------------------- + Exception / Interrupt Handler + *----------------------------------------------------------------------------*/ +/* Exceptions */ +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SecureFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void) __attribute__((weak, alias("Default_Handler"))); + +void Interrupt0_Handler(void) __attribute__((weak, alias("Default_Handler"))); +void Interrupt1_Handler(void) __attribute__((weak, alias("Default_Handler"))); +void Interrupt2_Handler(void) __attribute__((weak, alias("Default_Handler"))); +void Interrupt3_Handler(void) __attribute__((weak, alias("Default_Handler"))); +void Interrupt4_Handler(void) __attribute__((weak, alias("Default_Handler"))); +void Interrupt5_Handler(void) __attribute__((weak, alias("Default_Handler"))); +void Interrupt6_Handler(void) __attribute__((weak, alias("Default_Handler"))); +void Interrupt7_Handler(void) __attribute__((weak, alias("Default_Handler"))); +void Interrupt8_Handler(void) __attribute__((weak, alias("Default_Handler"))); +void Interrupt9_Handler(void) __attribute__((weak, alias("Default_Handler"))); + + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; +const VECTOR_TABLE_Type __VECTOR_TABLE[496] __VECTOR_TABLE_ATTRIBUTE = { + (VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */ + Reset_Handler, /* Reset Handler */ + NMI_Handler, /* -14 NMI Handler */ + HardFault_Handler, /* -13 Hard Fault Handler */ + MemManage_Handler, /* -12 MPU Fault Handler */ + BusFault_Handler, /* -11 Bus Fault Handler */ + UsageFault_Handler, /* -10 Usage Fault Handler */ + SecureFault_Handler, /* -9 Secure Fault Handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + SVC_Handler, /* -5 SVC Handler */ + DebugMon_Handler, /* -4 Debug Monitor Handler */ + 0, /* Reserved */ + PendSV_Handler, /* -2 PendSV Handler */ + SysTick_Handler, /* -1 SysTick Handler */ + + /* Interrupts */ + Interrupt0_Handler, /* 0 Interrupt 0 */ + Interrupt1_Handler, /* 1 Interrupt 1 */ + Interrupt2_Handler, /* 2 Interrupt 2 */ + Interrupt3_Handler, /* 3 Interrupt 3 */ + Interrupt4_Handler, /* 4 Interrupt 4 */ + Interrupt5_Handler, /* 5 Interrupt 5 */ + Interrupt6_Handler, /* 6 Interrupt 6 */ + Interrupt7_Handler, /* 7 Interrupt 7 */ + Interrupt8_Handler, /* 8 Interrupt 8 */ + Interrupt9_Handler /* 9 Interrupt 9 */ + /* Interrupts 10 .. 480 are left out */ +}; + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +/*---------------------------------------------------------------------------- + Reset Handler called on controller reset + *----------------------------------------------------------------------------*/ +__NO_RETURN void Reset_Handler(void) +{ + __set_PSP((uint32_t)(&__INITIAL_SP)); + + __set_MSPLIM(0); + __set_PSPLIM(0); + +#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL)); +#endif + + SystemInit(); /* CMSIS System Initialization */ + __PROGRAM_START(); /* Enter PreMain (C library entry point) */ +} + + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmissing-noreturn" +#endif + +/*---------------------------------------------------------------------------- + Default Handler for Exceptions / Interrupts + *----------------------------------------------------------------------------*/ +void Default_Handler(void) +{ + while (1) + ; +} + +#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) +#pragma clang diagnostic pop +#endif diff --git a/test/baremetal/platform/m55-an547/src/system_ARMCM55.c b/test/baremetal/platform/m55-an547/src/system_ARMCM55.c new file mode 100644 index 00000000..abded498 --- /dev/null +++ b/test/baremetal/platform/m55-an547/src/system_ARMCM55.c @@ -0,0 +1,108 @@ +/**************************************************************************/ /** + * @file system_ARMCM55.c + * @brief CMSIS Device System Source File for + * ARMCM55 Device + * @version V1.0.2 + * @date 13. Oct 2021 + ******************************************************************************/ +/* + * Copyright (c) 2009-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if defined(ARMCM55) +#include "ARMCM55.h" +#else +#error device not specified! +#endif + +#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#include "partition_ARMCM55.h" +#endif + +#include "uart.h" + +/*---------------------------------------------------------------------------- + Define clocks + *----------------------------------------------------------------------------*/ +#define XTAL (5000000UL) /* Oscillator frequency */ + +#define SYSTEM_CLOCK (5U * XTAL) + + +/*---------------------------------------------------------------------------- + Exception / Interrupt Vector table + *----------------------------------------------------------------------------*/ +extern const VECTOR_TABLE_Type __VECTOR_TABLE[496]; + + +/*---------------------------------------------------------------------------- + System Core Clock Variable + *----------------------------------------------------------------------------*/ +uint32_t SystemCoreClock = SYSTEM_CLOCK; + + +/*---------------------------------------------------------------------------- + System Core Clock update function + *----------------------------------------------------------------------------*/ +void SystemCoreClockUpdate(void) { SystemCoreClock = SYSTEM_CLOCK; } + +/*---------------------------------------------------------------------------- + System initialization function + *----------------------------------------------------------------------------*/ +void SystemInit(void) +{ +#if defined(__VTOR_PRESENT) && (__VTOR_PRESENT == 1U) + SCB->VTOR = (uint32_t)(&__VECTOR_TABLE[0]); +#endif + + /* #if (defined (__FPU_USED) && (__FPU_USED == 1U)) || \ */ + /* (defined (__ARM_FEATURE_MVE) && (__ARM_FEATURE_MVE > 0U)) */ + SCB->CPACR |= ((3U << 10U * 2U) | /* enable CP10 Full Access */ + (3U << 11U * 2U)); /* enable CP11 Full Access */ + + /* Set low-power state for PDEPU */ + /* 0b00 | ON, PDEPU is not in low-power state */ + /* 0b01 | ON, but the clock is off */ + /* 0b10 | RET(ention) */ + /* 0b11 | OFF */ + + /* Clear ELPSTATE, value is 0b11 on Cold reset */ + PWRMODCTL->CPDLPSTATE &= + ~(PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos); + + /* Favor best FP/MVE performance by default, avoid EPU switch-ON delays */ + /* PDEPU ON, Clock OFF */ + PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos; + /* #endif */ + +#ifdef UNALIGNED_SUPPORT_DISABLE + SCB->CCR |= SCB_CCR_UNALIGN_TRP_Msk; +#endif + + /* Enable Loop and branch info cache */ + SCB->CCR |= SCB_CCR_LOB_Msk; + __DSB(); + __ISB(); + +#if defined(__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) + TZ_SAU_Setup(); +#endif + + SystemCoreClock = SYSTEM_CLOCK; + + uart_init(); +} diff --git a/test/baremetal/platform/m55-an547/src/uart.c b/test/baremetal/platform/m55-an547/src/uart.c new file mode 100644 index 00000000..60c0f72d --- /dev/null +++ b/test/baremetal/platform/m55-an547/src/uart.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "uart.h" +#include +#include + +#define UART0_BASE 0x49303000 +#define UART0_BAUDRATE 115200 +#define SYSTEM_CORE_CLOCK 25000000 + +/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/ + +#define __IO volatile +#define __I volatile const +#define __O volatile + +typedef struct +{ + __IO uint32_t DATA; /* Offset: 0x000 (R/W) Data Register */ + __IO uint32_t STATE; /* Offset: 0x004 (R/W) Status Register */ + __IO uint32_t CTRL; /* Offset: 0x008 (R/W) Control Register */ + union + { + __I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */ + __O uint32_t INTCLEAR; /* Offset: 0x00C ( /W) Interrupt Clear Register */ + }; + __IO uint32_t BAUDDIV; /* Offset: 0x010 (R/W) Baudrate Divider Register */ +} CMSDK_UART_TypeDef; + +#define CMSDK_UART0_BASE UART0_BASE +#define CMSDK_UART0 ((CMSDK_UART_TypeDef *)CMSDK_UART0_BASE) +#define CMSDK_UART0_BAUDRATE UART0_BAUDRATE + +void uart_init(void) +{ + // SystemCoreClock / 9600 + CMSDK_UART0->BAUDDIV = SYSTEM_CORE_CLOCK / CMSDK_UART0_BAUDRATE; + + CMSDK_UART0->CTRL = ((1ul << 0) | /* TX enable */ + (1ul << 1)); /* RX enable */ +} + +// Output a character +unsigned char uart_putc(unsigned char my_ch) +{ + while ((CMSDK_UART0->STATE & 1)) + ; // Wait if Transmit Holding register is full + + if (my_ch == '\n') + { + CMSDK_UART0->DATA = '\r'; + while ((CMSDK_UART0->STATE & 1)) + ; // Wait if Transmit Holding register is full + } + + CMSDK_UART0->DATA = my_ch; // write to transmit holding register + + return (my_ch); +} + +// Get a character +unsigned char uart_getc(void) +{ + unsigned char my_ch; + // unsigned int cnt; + + while ((CMSDK_UART0->STATE & 2) == + 0) // Wait if Receive Holding register is empty + { +#if 0 + cnt = MPS3_FPGAIO->CLK100HZ / 50; + if (cnt & 0x8) + MPS3_FPGAIO->LED = 0x01 << (cnt & 0x7); + else + MPS3_FPGAIO->LED = 0x80 >> (cnt & 0x7); +#endif + } + + my_ch = CMSDK_UART0->DATA; + + // Convert CR to LF + if (my_ch == '\r') + { + my_ch = '\n'; + } + + return (my_ch); +} diff --git a/test/baremetal/platform/m55-an547/src/uart.h b/test/baremetal/platform/m55-an547/src/uart.h new file mode 100644 index 00000000..d06a37e7 --- /dev/null +++ b/test/baremetal/platform/m55-an547/src/uart.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019-2021 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _UART_STDOUT_H_ +#define _UART_STDOUT_H_ + +#if __cplusplus +extern "C" +{ +#endif + + void uart_init(void); + unsigned char uart_putc(unsigned char my_ch); + unsigned char uart_getc(void); + +#if __cplusplus +} +#endif + +#endif