ci: the emulated vector and SME legs bring their own emulator #674
2 changed files with 95 additions and 19 deletions
51
.github/workflows/wai-quantum-sme.yml
vendored
51
.github/workflows/wai-quantum-sme.yml
vendored
|
|
@ -5,9 +5,10 @@ name: wai-quantum matrix-extension member
|
|||
# against the CPU reference's pinned corpus digests.
|
||||
#
|
||||
# - sme-emulated (the container runner): the member's device tests for aarch64
|
||||
# Linux, run through the host's user-mode emulator (its binfmt handler, which
|
||||
# emulates SME); the runner declares the emulator, and every certificate says
|
||||
# it was earned there, never on silicon.
|
||||
# Linux, run under a user-mode emulator the job fetches and runs itself
|
||||
# (Debian's static QEMU, pinned, which emulates SME), never the host's binfmt
|
||||
# handler; the job declares the emulator, and every certificate says it was
|
||||
# earned there, never on silicon.
|
||||
# - sme-absent (the macOS runner, whose processor has no SME): the same build
|
||||
# finds no member and says why.
|
||||
#
|
||||
|
|
@ -62,12 +63,17 @@ jobs:
|
|||
options: --memory=6g --memory-swap=6g
|
||||
env:
|
||||
WAI_QUANTUM_SME_EXPECT: cpu-matrix-sme
|
||||
# The host's binfmt handler runs every aarch64 binary; its emulator is
|
||||
# what the certificates name.
|
||||
WAI_QUANTUM_SME_EMULATOR: qemu-user 8.2.2 (the host's binfmt handler)
|
||||
# Run the test binary directly, so the host's handler (which emulates
|
||||
# SME) runs it, not the image's older emulator.
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER: env
|
||||
# The emulator every aarch64 test binary runs under, which the certificates
|
||||
# name: Debian's static QEMU, SHA-256 pinned, fetched by the job and named as
|
||||
# cargo's runner. Not the image's own (5.1), and not the host's binfmt
|
||||
# handler, which some `linux` runners lack and others run at another
|
||||
# version. (Not QEMU_*: qemu-user reads every QEMU_<option> variable as that
|
||||
# option.)
|
||||
WAI_QUANTUM_SME_EMULATOR: qemu-user 10.0.13 (Debian's static build, run by the job)
|
||||
USER_EMULATOR_VERSION: 10.0.13
|
||||
USER_EMULATOR_DEB: qemu-user_10.0.13+ds-0+deb13u1_amd64.deb
|
||||
USER_EMULATOR_SHA256: ca6ede739327a20ae5a3498230c8a3a9a072c586e131bc6bcc1201eb1725e336
|
||||
USER_EMULATOR_SHA1: dec1373851d29f91642c197f4a339d0d2ad25ed0
|
||||
steps:
|
||||
# The image has no Node for a checkout action: the forge's archive of the
|
||||
# exact commit, its embedded commit id checked.
|
||||
|
|
@ -99,6 +105,33 @@ jobs:
|
|||
fi
|
||||
rustup toolchain install
|
||||
rustup target add aarch64-unknown-linux-gnu
|
||||
# The emulator, fetched once per host into the cache (under the lock above)
|
||||
# and checked against its pin, then named as cargo's runner, so this leg
|
||||
# passes or fails the same on every `linux` runner.
|
||||
q="$cache/qemu-user-$USER_EMULATOR_VERSION"
|
||||
if [ ! -x "$q/qemu-aarch64" ]; then
|
||||
d="$cache/qemu-user-fetch"; rm -rf "$d" && mkdir "$d"
|
||||
curl -sSfL -o "$d/$USER_EMULATOR_DEB" "https://deb.debian.org/debian/pool/main/q/qemu/$USER_EMULATOR_DEB" \
|
||||
|| curl -sSfL -o "$d/$USER_EMULATOR_DEB" "https://snapshot.debian.org/file/$USER_EMULATOR_SHA1"
|
||||
echo "$USER_EMULATOR_SHA256 $d/$USER_EMULATOR_DEB" | sha256sum -c -
|
||||
dpkg-deb --fsys-tarfile "$d/$USER_EMULATOR_DEB" | tar -x -C "$d" ./usr/bin/qemu-aarch64
|
||||
rm -rf "$q.tmp" && mkdir "$q.tmp" && mv "$d/usr/bin/qemu-aarch64" "$q.tmp/"
|
||||
rm -rf "$q" && mv "$q.tmp" "$q" && rm -rf "$d"
|
||||
fi
|
||||
runner="$q/qemu-aarch64 -L /usr/aarch64-linux-gnu"
|
||||
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER="$runner"
|
||||
# Preflight: a trivial program, built for the target and run as cargo will run
|
||||
# the tests. An emulator that cannot run it fails the leg here, saying so,
|
||||
# rather than as a test that never ran.
|
||||
cat > "$RUNNER_TEMP/probe.c" <<'EOF'
|
||||
#include <stdio.h>
|
||||
#include <sys/utsname.h>
|
||||
int main(void) { struct utsname u; if (uname(&u) != 0) return 1; printf("%s\n", u.machine); return 0; }
|
||||
EOF
|
||||
aarch64-linux-gnu-gcc -o "$RUNNER_TEMP/probe" "$RUNNER_TEMP/probe.c"
|
||||
got="$($runner "$RUNNER_TEMP/probe")" || { echo "::error::the emulator cannot run an aarch64 program: $runner"; exit 1; }
|
||||
[ "$got" = aarch64 ] || { echo "::error::the preflight program ran as $got, not aarch64"; exit 1; }
|
||||
echo "emulator: $("$q/qemu-aarch64" --version | head -1); an aarch64 program runs under it"
|
||||
report="$(mktemp)"
|
||||
WAI_QUANTUM_SME_REPORT="$report" cargo test --locked --release -j 6 --target aarch64-unknown-linux-gnu --features quantum_fabric_sme --test sme_member -- --test-threads=1 2>&1 | tee "$cache/device.log"
|
||||
grep -qE '^test result: ok\. 9 passed; 0 failed' "$cache/device.log" || { echo "::error::not every device test ran and passed"; exit 1; }
|
||||
|
|
|
|||
63
.github/workflows/wai-quantum-vector.yml
vendored
63
.github/workflows/wai-quantum-vector.yml
vendored
|
|
@ -10,7 +10,8 @@ name: wai-quantum CPU vector units
|
|||
# checks the avx2 member as on any other;
|
||||
# - avx2 and avx512 on silicon together: framework-128gb's processor, which has
|
||||
# both, one member each;
|
||||
# - sve and rvv under the host's user-mode emulator (its binfmt handler), at
|
||||
# - sve and rvv under a user-mode emulator the job fetches and runs itself
|
||||
# (Debian's static QEMU, pinned), never the host's binfmt handler, at
|
||||
# several vector lengths each: the scalable kernels set their length per
|
||||
# pass, and every leg checks the length the member read from the unit is the
|
||||
# one the emulator was given, so a leg cannot pass at the wrong length;
|
||||
|
|
@ -74,41 +75,47 @@ jobs:
|
|||
key: cpu-vector-avx2
|
||||
bits: 256
|
||||
emulator: ''
|
||||
qemu: ''
|
||||
qemu_cpu: ''
|
||||
- name: sve 128-bit (aarch64, emulated)
|
||||
target: aarch64-unknown-linux-gnu
|
||||
image: ghcr.io/cross-rs/aarch64-unknown-linux-gnu@sha256:7f8308a8734d9fcd2ebbe9a3e4bdea74af293f0799d80c3cc341e340cda49a4c
|
||||
key: cpu-vector-sve
|
||||
bits: 128
|
||||
emulator: qemu-user 8.2.2 (the host's binfmt handler)
|
||||
emulator: qemu-user 10.0.13 (Debian's static build, run by the job)
|
||||
qemu: aarch64
|
||||
qemu_cpu: max,sve-default-vector-length=16
|
||||
- name: sve 512-bit (aarch64, emulated)
|
||||
target: aarch64-unknown-linux-gnu
|
||||
image: ghcr.io/cross-rs/aarch64-unknown-linux-gnu@sha256:7f8308a8734d9fcd2ebbe9a3e4bdea74af293f0799d80c3cc341e340cda49a4c
|
||||
key: cpu-vector-sve
|
||||
bits: 512
|
||||
emulator: qemu-user 8.2.2 (the host's binfmt handler)
|
||||
emulator: qemu-user 10.0.13 (Debian's static build, run by the job)
|
||||
qemu: aarch64
|
||||
qemu_cpu: max,sve-default-vector-length=64
|
||||
- name: sve 2048-bit (aarch64, emulated)
|
||||
target: aarch64-unknown-linux-gnu
|
||||
image: ghcr.io/cross-rs/aarch64-unknown-linux-gnu@sha256:7f8308a8734d9fcd2ebbe9a3e4bdea74af293f0799d80c3cc341e340cda49a4c
|
||||
key: cpu-vector-sve
|
||||
bits: 2048
|
||||
emulator: qemu-user 8.2.2 (the host's binfmt handler)
|
||||
emulator: qemu-user 10.0.13 (Debian's static build, run by the job)
|
||||
qemu: aarch64
|
||||
qemu_cpu: max,sve-default-vector-length=256
|
||||
- name: rvv 128-bit (riscv64, emulated)
|
||||
target: riscv64gc-unknown-linux-gnu
|
||||
image: ghcr.io/cross-rs/riscv64gc-unknown-linux-gnu@sha256:67ee97dd4719390d299edfcf39f226360ccfb1539e08b078ec187d4848415794
|
||||
key: cpu-vector-rvv
|
||||
bits: 128
|
||||
emulator: qemu-user 8.2.2 (the host's binfmt handler)
|
||||
emulator: qemu-user 10.0.13 (Debian's static build, run by the job)
|
||||
qemu: riscv64
|
||||
qemu_cpu: rv64,v=true,vlen=128,elen=64
|
||||
- name: rvv 1024-bit (riscv64, emulated)
|
||||
target: riscv64gc-unknown-linux-gnu
|
||||
image: ghcr.io/cross-rs/riscv64gc-unknown-linux-gnu@sha256:67ee97dd4719390d299edfcf39f226360ccfb1539e08b078ec187d4848415794
|
||||
key: cpu-vector-rvv
|
||||
bits: 1024
|
||||
emulator: qemu-user 8.2.2 (the host's binfmt handler)
|
||||
emulator: qemu-user 10.0.13 (Debian's static build, run by the job)
|
||||
qemu: riscv64
|
||||
qemu_cpu: rv64,v=true,vlen=1024,elen=64
|
||||
container:
|
||||
image: ${{ matrix.image }}
|
||||
|
|
@ -116,10 +123,16 @@ jobs:
|
|||
env:
|
||||
WAI_QUANTUM_VECTOR_EXPECT: ${{ matrix.key }}
|
||||
WAI_QUANTUM_VECTOR_EMULATOR: ${{ matrix.emulator }}
|
||||
# Run test binaries directly, so the host's handler runs them with the
|
||||
# processor given here, not the image's older emulator.
|
||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER: env
|
||||
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER: env
|
||||
# The emulator every foreign test binary runs under: Debian's static QEMU,
|
||||
# SHA-256 pinned, fetched by the job and named as cargo's runner. Not the
|
||||
# image's own (5.1 for aarch64, 6.1 for riscv64), and not the host's binfmt
|
||||
# handler, which some `linux` runners lack and others run at another
|
||||
# version. (Not QEMU_*: qemu-user reads every QEMU_<option> variable as that
|
||||
# option.)
|
||||
USER_EMULATOR_VERSION: 10.0.13
|
||||
USER_EMULATOR_DEB: qemu-user_10.0.13+ds-0+deb13u1_amd64.deb
|
||||
USER_EMULATOR_SHA256: ca6ede739327a20ae5a3498230c8a3a9a072c586e131bc6bcc1201eb1725e336
|
||||
USER_EMULATOR_SHA1: dec1373851d29f91642c197f4a339d0d2ad25ed0
|
||||
steps:
|
||||
# The image has no Node for a checkout action: the forge's archive of the
|
||||
# exact commit, its embedded commit id checked.
|
||||
|
|
@ -153,6 +166,36 @@ jobs:
|
|||
rustup target add ${{ matrix.target }}
|
||||
# The emulated processor, for the test binaries only.
|
||||
if [ -n "${{ matrix.qemu_cpu }}" ]; then export QEMU_CPU="${{ matrix.qemu_cpu }}"; fi
|
||||
# A trivial program for the preflight below: it prints the machine it runs on.
|
||||
cat > "$RUNNER_TEMP/probe.c" <<'EOF'
|
||||
#include <stdio.h>
|
||||
#include <sys/utsname.h>
|
||||
int main(void) { struct utsname u; if (uname(&u) != 0) return 1; printf("%s\n", u.machine); return 0; }
|
||||
EOF
|
||||
if [ -n "${{ matrix.qemu }}" ]; then
|
||||
# The emulator, fetched once per host into the cache (under the lock above)
|
||||
# and checked against its pin, then named as cargo's runner, so this leg
|
||||
# passes or fails the same on every `linux` runner.
|
||||
q="$cache/qemu-user-$USER_EMULATOR_VERSION"
|
||||
if [ ! -x "$q/qemu-aarch64" ] || [ ! -x "$q/qemu-riscv64" ]; then
|
||||
d="$cache/qemu-user-fetch"; rm -rf "$d" && mkdir "$d"
|
||||
curl -sSfL -o "$d/$USER_EMULATOR_DEB" "https://deb.debian.org/debian/pool/main/q/qemu/$USER_EMULATOR_DEB" \
|
||||
|| curl -sSfL -o "$d/$USER_EMULATOR_DEB" "https://snapshot.debian.org/file/$USER_EMULATOR_SHA1"
|
||||
echo "$USER_EMULATOR_SHA256 $d/$USER_EMULATOR_DEB" | sha256sum -c -
|
||||
dpkg-deb --fsys-tarfile "$d/$USER_EMULATOR_DEB" | tar -x -C "$d" ./usr/bin/qemu-aarch64 ./usr/bin/qemu-riscv64
|
||||
rm -rf "$q.tmp" && mkdir "$q.tmp" && mv "$d/usr/bin/qemu-aarch64" "$d/usr/bin/qemu-riscv64" "$q.tmp/"
|
||||
rm -rf "$q" && mv "$q.tmp" "$q" && rm -rf "$d"
|
||||
fi
|
||||
runner="$q/qemu-${{ matrix.qemu }} -L /usr/${{ matrix.qemu }}-linux-gnu"
|
||||
export "CARGO_TARGET_$(printf %s "${{ matrix.target }}" | tr 'a-z-' 'A-Z_')_RUNNER=$runner"
|
||||
# Preflight: the trivial program, built for the target and run as cargo will
|
||||
# run the tests. An emulator that cannot run it fails the leg here, saying
|
||||
# so, rather than as a test that never ran.
|
||||
"${{ matrix.qemu }}-linux-gnu-gcc" -o "$RUNNER_TEMP/probe" "$RUNNER_TEMP/probe.c"
|
||||
got="$($runner "$RUNNER_TEMP/probe")" || { echo "::error::the emulator cannot run a program for ${{ matrix.target }}: $runner"; exit 1; }
|
||||
[ "$got" = "${{ matrix.qemu }}" ] || { echo "::error::the preflight program ran as $got, not ${{ matrix.qemu }}"; exit 1; }
|
||||
echo "emulator: $("$q/qemu-${{ matrix.qemu }}" --version | head -1), cpu ${QEMU_CPU:-default}; a program for ${{ matrix.target }} runs under it"
|
||||
fi
|
||||
# Every unit this processor has must be declared, so on silicon the
|
||||
# declaration comes from the kernel's own flags, not the probe under test.
|
||||
if [ "${{ matrix.key }}" = cpu-vector-avx2 ] && grep -qw avx512f /proc/cpuinfo; then
|
||||
|
|
|
|||
Loading…
Reference in a new issue