Skip to content

Commit bae13fa

Browse files
committed
Port: Baremetal: Add Cortex-M33 MPS3-AN524 platform support
This commit is ported from pq-code-package/mldsa-native#950, and the commit message below is same as original commit in mldsa-native. Add bare-metal platform support for Cortex-M33 on MPS3-AN524, tested via qemu (qemu-system-arm -M mps3-an524). Notice that the configuration *_CONFIG_REDUCE_RAM did not implement in mlkem-native, we skip this option during this porting. - Add platform makefile and qemu exec wrapper for M33-AN524 - Platform files are provided by pqmx, see slothy-optimizer/pqmx#116 - Add Cortex-M33 DWT cycle counter support in HAL (distinct from Cortex-M55 PMU-based counting) - Generalize Nix package from m55-an547 to pqmx to serve both M55-AN547 and M33-AN524 platforms - Allow MLD_BUMP_ALLOC_SIZE to be overridden at compile time (we only have a 96 KiB stack) - Add M33 baremetal test to CI matrix Signed-off-by: willieyz <willie.zhao@chelpis.com>
1 parent 566920d commit bae13fa

8 files changed

Lines changed: 179 additions & 8 deletions

File tree

.github/workflows/baremetal.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ jobs:
2626
alloc: true
2727
bench: true
2828
opt: all
29+
- runner: ubuntu-latest
30+
name: 'M33-AN524'
31+
makefile: test/baremetal/platform/m33-an524/platform.mk
32+
nix-shell: cross-arm-embedded
33+
func: true
34+
kat: true
35+
acvp: true
36+
alloc: true
37+
bench: true
38+
opt: no_opt
2939
- runner: ubuntu-latest
3040
name: 'AVR ATmega128RFR2 (modified for 32K RAM)'
3141
makefile: test/baremetal/platform/avr/platform.mk

flake.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152
devShells.cross-arm-embedded = util.mkShell {
153153
packages = builtins.attrValues
154154
{
155-
inherit (util) m55-an547;
155+
inherit (util) pqmx;
156156
inherit (config.packages) linters;
157157
inherit (pkgs) gcc-arm-embedded qemu coreutils python3 git;
158158
};
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,37 @@
88
}:
99

1010
stdenvNoCC.mkDerivation {
11-
pname = "mlkem-native-m55-an547";
12-
version = "main-2025-10-02";
11+
pname = "mlkem-native-pqmx";
12+
version = "main-2026-02-25";
1313

1414

15-
# Fetch platform files from pqmx (envs/m55-an547)
15+
# Fetch platform files from pqmx
1616
src = fetchFromGitHub {
1717
owner = "slothy-optimizer";
1818
repo = "pqmx";
19-
rev = "4ed493d3cf2af62a08fd9fe36c3472a0dc50ad9f";
20-
hash = "sha256-jLIqwknjRwcoDeEAETlMhRqZQ5a3QGCDZX9DENelGeQ=";
19+
rev = "526abcbccd022f0c384e70c7d00f2b36cd2199ab";
20+
hash = "sha256-BjsToEWGlykKIKRfPom84BkD5RfetUKKwRAw3PecebU=";
2121
};
2222

2323
dontBuild = true;
2424

2525
installPhase = ''
26+
mkdir -p $out/platform/m33-an524/src/platform/
27+
cp -r envs/m33-an524/src/platform/. $out/platform/m33-an524/src/platform/
28+
cp integration/*.c $out/platform/m33-an524/src/platform/
29+
2630
mkdir -p $out/platform/m55-an547/src/platform/
2731
cp -r envs/m55-an547/src/platform/. $out/platform/m55-an547/src/platform/
2832
cp integration/*.c $out/platform/m55-an547/src/platform/
2933
'';
3034

3135
setupHook = writeText "setup-hook.sh" ''
36+
export M33_AN524_PATH="$1/platform/m33-an524/src/platform/"
3237
export M55_AN547_PATH="$1/platform/m55-an547/src/platform/"
3338
'';
3439

3540
meta = {
36-
description = "Platform files for the Cortex-M55 (AN547)";
41+
description = "Platform files from pqmx for baremetal targets";
3742
homepage = "https://github.com/slothy-optimizer/pqmx";
3843
};
3944
}

nix/util.nix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ rec {
101101
hol_server = pkgs.callPackage ./hol_light/hol_server.nix { inherit hol_light'; };
102102
s2n_bignum = pkgs.callPackage ./s2n_bignum { };
103103
slothy = pkgs.callPackage ./slothy { python3 = python3-for-slothy; };
104-
m55-an547 = pkgs.callPackage ./m55-an547-arm-none-eabi { };
104+
pqmx = pkgs.callPackage ./pqmx { };
105105
avr-toolchain = pkgs.callPackage ./avr { };
106106

107107
# Helper function to build individual cross toolchains
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) The mldsa-native project authors
3+
# Copyright (c) The mlkem-native project authors
4+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
5+
6+
"""QEMU wrapper for executing Cortex-M33 bare-metal ELF binaries (mps3-an524)."""
7+
8+
import struct as st
9+
import sys
10+
import subprocess
11+
import tempfile
12+
import os
13+
14+
15+
def err(msg, **kwargs):
16+
print(msg, file=sys.stderr, **kwargs)
17+
18+
19+
binpath = sys.argv[1]
20+
args = sys.argv[1:]
21+
22+
# Memory layout: [argc] [offset1] [offset2] ... [string1\0] [string2\0] ...
23+
# M33-AN524 RAM: 0x20000000-0x2001FFFF (128KB)
24+
# Heap ends at: ~0x20000b20
25+
# Stack: 0x20008000-0x2001FFFF (96KB, grows downward)
26+
# Use address after heap but before stack
27+
# cmdline.c CMDLINE_ADDR must match this value
28+
cmdline_offset = 0x20007000
29+
arg0_offset = cmdline_offset + 4 + len(args) * 4
30+
arg_offsets = [sum(map(len, args[:i])) + i + arg0_offset for i in range(len(args))]
31+
32+
binargs = st.pack(
33+
f"<{1+len(args)}I" + "".join(f"{len(a)+1}s" for a in args),
34+
len(args),
35+
*arg_offsets,
36+
*map(lambda x: x.encode("utf-8"), args),
37+
)
38+
39+
with tempfile.NamedTemporaryFile(mode="wb", delete=False, suffix=".bin") as fd:
40+
args_file = fd.name
41+
fd.write(binargs)
42+
43+
try:
44+
qemu_cmd = f"qemu-system-arm -M mps3-an524 -cpu cortex-m33 -nographic -semihosting -kernel {binpath} -device loader,file={args_file},addr=0x{cmdline_offset:x}".split()
45+
result = subprocess.run(qemu_cmd, encoding="utf-8", capture_output=True)
46+
finally:
47+
os.unlink(args_file)
48+
if result.returncode != 0:
49+
err("FAIL!")
50+
err(f"{qemu_cmd} failed with error code {result.returncode}")
51+
err(result.stderr)
52+
exit(1)
53+
54+
for line in result.stdout.splitlines():
55+
print(line)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Copyright (c) The mldsa-native project authors
2+
# Copyright (c) The mlkem-native project authors
3+
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
4+
5+
PLATFORM_PATH:=test/baremetal/platform/m33-an524
6+
7+
CROSS_PREFIX=arm-none-eabi-
8+
CC=gcc
9+
10+
# Use PMU cycle counting by default
11+
CYCLES ?= PMU
12+
13+
# Reduce iterations for benchmarking
14+
CFLAGS += -DMLK_BENCHMARK_NTESTS=3 -DMLK_BENCHMARK_NITERATIONS=2 -DMLK_BENCHMARK_NWARMUP=3
15+
16+
CFLAGS += -DMLK_BUMP_ALLOC_SIZE=65536
17+
18+
CFLAGS += \
19+
-O3 \
20+
-Wall -Wextra -Wshadow \
21+
-Wno-pedantic \
22+
-Wno-redundant-decls \
23+
-Wno-missing-prototypes \
24+
-Wno-conversion \
25+
-Wno-sign-conversion \
26+
-fno-common \
27+
-ffunction-sections \
28+
-fdata-sections \
29+
--sysroot=$(SYSROOT) \
30+
-DDEVICE=an524 \
31+
-I$(M33_AN524_PATH) \
32+
-I$(M33_AN524_PATH)/m-profile \
33+
-DARMCM33 \
34+
-DSEMIHOSTING \
35+
-DCMDLINE_BASE_ADDR=0x20007000
36+
37+
ARCH_FLAGS += \
38+
-mcpu=cortex-m33 \
39+
-mthumb \
40+
-mfloat-abi=soft
41+
42+
CFLAGS += \
43+
$(ARCH_FLAGS) \
44+
--specs=nosys.specs
45+
46+
CFLAGS += $(CFLAGS_EXTRA)
47+
48+
LDSCRIPT = $(M33_AN524_PATH)/m33-an524.ld
49+
50+
LDFLAGS += \
51+
-Wl,--gc-sections \
52+
-Wl,--no-warn-rwx-segments \
53+
-L.
54+
55+
LDFLAGS += \
56+
--specs=nosys.specs \
57+
-Wl,--wrap=_open \
58+
-Wl,--wrap=_close \
59+
-Wl,--wrap=_read \
60+
-Wl,--wrap=_write \
61+
-Wl,--wrap=_fstat \
62+
-Wl,--wrap=_getpid \
63+
-Wl,--wrap=_isatty \
64+
-Wl,--wrap=_kill \
65+
-Wl,--wrap=_lseek \
66+
-Wl,--wrap=main \
67+
-ffreestanding \
68+
-T$(LDSCRIPT) \
69+
$(ARCH_FLAGS)
70+
71+
# Extra sources to be included in test binaries
72+
EXTRA_SOURCES = $(wildcard $(M33_AN524_PATH)/*.c)
73+
# The CMSIS files fail compilation if conversion warnings are enabled
74+
EXTRA_SOURCES_CFLAGS = -Wno-conversion -Wno-sign-conversion
75+
76+
EXEC_WRAPPER := $(realpath $(PLATFORM_PATH)/exec_wrapper.py)

test/hal/hal.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,25 @@ uint64_t get_cyclecounter(void)
9595
}
9696

9797
#elif defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8_1M_MAIN__)
98+
/* ARMv8-M cycle counting support */
99+
#if defined(ARMCM33)
100+
/* Cortex-M33: Use DWT cycle counter (no dedicated PMU) */
101+
#include <ARMCM33.h>
102+
#include <system_ARMCM33.h>
103+
104+
void enable_cyclecounter(void)
105+
{
106+
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
107+
DWT->CYCCNT = 0;
108+
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
109+
}
110+
111+
void disable_cyclecounter(void) { DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; }
112+
113+
uint64_t get_cyclecounter(void) { return DWT->CYCCNT; }
114+
115+
#elif defined(ARMCM55)
116+
/* Cortex-M55: Use dedicated PMU */
98117
#include <ARMCM55.h>
99118
#include <system_ARMCM55.h>
100119
#include "pmu_armv8.h"
@@ -115,6 +134,10 @@ void disable_cyclecounter(void)
115134

116135
uint64_t get_cyclecounter(void) { return ARM_PMU_Get_CCNTR(); }
117136

137+
#else /* !ARMCM33 && ARMCM55 */
138+
#error "PMU_CYCLES on ARMv8-M requires ARMCM33 or ARMCM55 to be defined"
139+
#endif /* !ARMCM33 && !ARMCM55 */
140+
118141
#elif defined(__riscv)
119142

120143
void enable_cyclecounter(void) {}

test/src/test_alloc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ typedef struct
7070
} alloc_info_t;
7171

7272
#define MLK_MAX_IN_FLIGHT_ALLOCS 100
73+
#ifndef MLK_BUMP_ALLOC_SIZE
7374
#define MLK_BUMP_ALLOC_SIZE (24 * 1024) /* 24KB buffer */
75+
#endif
7476

7577
struct test_ctx_t
7678
{

0 commit comments

Comments
 (0)