From 94348cb341015dee5a69c88e2887dde7d080964f Mon Sep 17 00:00:00 2001 From: Hongyu Ning Date: Sun, 21 Jun 2026 22:30:25 +0800 Subject: [PATCH 1/5] BM/ras: add rasdaemon and mce-inject submodules, re-pin mce-test - Add rasdaemon (github.com/mchehab/rasdaemon @ a4620eb). - Add mce-inject (git.kernel.org/.../mce-inject @ ca81c1d). - Re-point mce-test from a personal fork to canonical upstream (git.kernel.org/.../mce-test) and re-pin to dbbbc64, which is reachable in upstream master (1 commit behind tip)." Signed-off-by: Hongyu Ning --- .gitmodules | 8 +++++++- BM/ras/mce-inject | 1 + BM/ras/mce-test | 2 +- BM/ras/rasdaemon | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) create mode 160000 BM/ras/mce-inject create mode 160000 BM/ras/rasdaemon diff --git a/.gitmodules b/.gitmodules index 7bc07f0b..529ac4d0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,10 +5,16 @@ branch = stable [submodule "BM/ras/mce-test"] path = BM/ras/mce-test - url = https://github.com/laifryiee/mce-test.git + url = https://git.kernel.org/pub/scm/utils/cpu/mce/mce-test.git [submodule "BM/ras/ras-tools"] path = BM/ras/ras-tools url = https://git.kernel.org/pub/scm/linux/kernel/git/aegl/ras-tools.git [submodule "BM/ras/mcelog"] path = BM/ras/mcelog url = https://github.com/andikleen/mcelog.git +[submodule "BM/ras/mce-inject"] + path = BM/ras/mce-inject + url = https://git.kernel.org/pub/scm/utils/cpu/mce/mce-inject.git +[submodule "BM/ras/rasdaemon"] + path = BM/ras/rasdaemon + url = https://github.com/mchehab/rasdaemon.git diff --git a/BM/ras/mce-inject b/BM/ras/mce-inject new file mode 160000 index 00000000..ca81c1db --- /dev/null +++ b/BM/ras/mce-inject @@ -0,0 +1 @@ +Subproject commit ca81c1dbed5c7e30fe79d44953ccfeaab98d2b4f diff --git a/BM/ras/mce-test b/BM/ras/mce-test index 6e394800..dbbbc64a 160000 --- a/BM/ras/mce-test +++ b/BM/ras/mce-test @@ -1 +1 @@ -Subproject commit 6e394800ff9e98837ad27b159822ab2c428d62c3 +Subproject commit dbbbc64a4b6e539cd39427f7dc3cb60400e02334 diff --git a/BM/ras/rasdaemon b/BM/ras/rasdaemon new file mode 160000 index 00000000..a4620eb3 --- /dev/null +++ b/BM/ras/rasdaemon @@ -0,0 +1 @@ +Subproject commit a4620eb301c7bbef51bb831e859eb01e6f9c6ac0 From 0e11d4ad17a0403a2e28a2f85de3d7b5927c9b72 Mon Sep 17 00:00:00 2001 From: Hongyu Ning Date: Sun, 21 Jun 2026 22:32:00 +0800 Subject: [PATCH 2/5] BM/ras: refresh Makefile, tests and helper scripts Signed-off-by: Hongyu Ning --- BM/ras/Makefile | 83 ++++++++++++++++++--- BM/ras/README.md | 49 ++++++++++++- BM/ras/bff_test.sh | 65 +++++++++++++++++ BM/ras/einjv2_test.sh | 165 ++++++++++++++++++++++++++++++++++++++++++ BM/ras/lmce_test.sh | 8 +- BM/ras/mce_test.sh | 30 ++++---- BM/ras/ras_common.sh | 114 +++++++++++++++++++++++------ BM/ras/tests | 14 +++- 8 files changed, 472 insertions(+), 56 deletions(-) create mode 100755 BM/ras/bff_test.sh create mode 100755 BM/ras/einjv2_test.sh diff --git a/BM/ras/Makefile b/BM/ras/Makefile index 896e1052..90887971 100644 --- a/BM/ras/Makefile +++ b/BM/ras/Makefile @@ -1,24 +1,83 @@ -SUBDIRS := mce-test ras-tools mcelog +SUBDIRS := mce-test mce-inject ras-tools +INSTALL_SUBDIRS := mce-test mce-inject + +# Detect distro-packaged mcelog/rasdaemon (not our own /usr/local installs) +SYSTEM_MCELOG := $(shell rpm -q mcelog 2>/dev/null | grep -v "not installed" || dpkg -s mcelog 2>/dev/null | grep -q "ok installed" && echo yes) +SYSTEM_RASDAEMON := $(shell rpm -q rasdaemon 2>/dev/null | grep -v "not installed" || dpkg -s rasdaemon 2>/dev/null | grep -q "ok installed" && echo yes) + +# Build from submodule only if not provided by distro package +ifeq ($(SYSTEM_MCELOG),) + SUBDIRS += mcelog + INSTALL_SUBDIRS += mcelog +endif + +ifeq ($(SYSTEM_RASDAEMON),) + SUBDIRS += rasdaemon + INSTALL_SUBDIRS += rasdaemon +endif + +# Filter out targets with custom build rules +GENERIC_SUBDIRS := $(filter-out rasdaemon,$(SUBDIRS)) .PHONY: all all: $(SUBDIRS) -.PHONY: $(SUBDIRS) -$(SUBDIRS): +.PHONY: $(GENERIC_SUBDIRS) +$(GENERIC_SUBDIRS): $(MAKE) -C $@ +.PHONY: rasdaemon +rasdaemon: + cd rasdaemon && \ + if [ ! -x ./configure ]; then \ + autoreconf -i; \ + fi && \ + if [ ! -f ./Makefile ]; then \ + ./configure --enable-sqlite3 --enable-mce \ + --enable-extlog --enable-memory-failure --enable-memory-ce-pfa; \ + fi && \ + $(MAKE) + .PHONY: install install: - for dir in $(SUBDIRS); do \ - if [ "$$dir" = "mce-test" ]; then \ - $(MAKE) -C $$dir install; \ - else \ - echo "Skipping install in $$dir"; \ - fi \ + for dir in $(INSTALL_SUBDIRS); do \ + $(MAKE) -C $$dir install; \ + done +ifeq ($(SYSTEM_RASDAEMON),) + @# Install rasdaemon systemd service only if distro doesn't provide one + @if [ ! -f /usr/lib/systemd/system/rasdaemon.service ]; then \ + install -D -m 644 rasdaemon/misc/rasdaemon.service /etc/systemd/system/rasdaemon.service; \ + fi + @if [ ! -f /etc/sysconfig/rasdaemon ]; then \ + install -D -m 644 rasdaemon/misc/rasdaemon.env /etc/sysconfig/rasdaemon 2>/dev/null || \ + touch /etc/sysconfig/rasdaemon; \ + fi + mkdir -p /usr/local/var/lib/rasdaemon + systemctl daemon-reload + systemctl enable rasdaemon + @if systemctl is-active --quiet rasdaemon; then \ + systemctl restart rasdaemon; \ + fi +endif + +.PHONY: uninstall +uninstall: + for dir in $(INSTALL_SUBDIRS); do \ + $(MAKE) -C $$dir uninstall 2>/dev/null || true; \ done + @# Stop and remove custom service file if we installed it + -systemctl stop rasdaemon 2>/dev/null + -systemctl disable rasdaemon 2>/dev/null + rm -f /etc/systemd/system/rasdaemon.service + @# Remove submodule-built rasdaemon data + rm -rf /usr/local/var/lib/rasdaemon/ + systemctl daemon-reload .PHONY: clean clean: - for dir in $(SUBDIRS); do \ - $(MAKE) -C $$dir clean; \ - done \ No newline at end of file + for dir in $(GENERIC_SUBDIRS); do \ + if [ -f $$dir/Makefile ]; then $(MAKE) -C $$dir clean; fi; \ + done + @# Use distclean for rasdaemon to remove autotools-generated files + @# so that configure is re-run on the next build. + if [ -f rasdaemon/Makefile ]; then $(MAKE) -C rasdaemon distclean; fi diff --git a/BM/ras/README.md b/BM/ras/README.md index b65595b1..e9840d51 100644 --- a/BM/ras/README.md +++ b/BM/ras/README.md @@ -2,8 +2,36 @@ Intel Xeon processor Scalable family supports various Reliability, Availability, and Serviceability (RAS) features across the product lineup. +This test suite targets Intel 10nm+ server platforms (ICX, SPR, EMR, GNR, SRF, CWF, DMR). +The EDAC driver loaded is `i10nm_edac` for Family 6 or `imh_edac` for Family 19 (DMR+). + Current BM/ras covers following features: * basic error injection +* EINJv2 memory error injection +* LMCE (Local Machine Check Exception) +* MCE corrected error threshold (yellow status via mce-inject) + +## Submodules + +| Submodule | Source | Purpose | +|-----------|--------|---------| +| mce-test | kernel.org | MCE test suite (APEI, EINJ, EMCA, ERST, PFA, etc.) | +| mce-inject | kernel.org | MCE event injection tool | +| ras-tools | kernel.org | LMCE injection binary | +| mcelog | github.com/andikleen | Machine check event logger (legacy) | +| rasdaemon | github.com/mchehab | RAS daemon using kernel tracepoints (modern) | + +## MCE Logging Backend + +The test suite supports two MCE logging backends: +- **mcelog** — legacy daemon reading from `/dev/mcelog` +- **rasdaemon** — modern daemon using kernel tracepoints, stores events in SQLite + +The Makefile automatically detects which is installed on your system: +- If a backend is already installed from your distro packages, it will be used as-is. +- If neither is found, both are built from their respective submodules. + +Most tests (`tests`) work with either backend. Tests in `tests_mcelog` require mcelog specifically. ## Usage Before test case execution: @@ -11,10 +39,25 @@ Before test case execution: ``` git submodule update --init --recursive ``` -2. make sure required packages are installed: +2. install the MCE logging backend from your distribution (preferred): +``` +# Option A: mcelog (legacy, CentOS/RHEL 7) +yum install mcelog + +# Option B: rasdaemon (modern, RHEL 8+, Fedora, Ubuntu 22.04+) +yum install rasdaemon # or: apt install rasdaemon +``` +If neither is available from your distro, the Makefile will build from the submodule. + +3. build the test suite (only builds submodules not already installed): +``` +make +sudo make install +``` +4. make sure other required packages are installed: ``` -yum install msr-tools cpuid mcelog screen # for CentOS -apt install msr-tools cpuid mcelog screen # for Debian/Ubuntu +yum install msr-tools cpuid screen # for CentOS/RHEL +apt install msr-tools cpuid screen # for Debian/Ubuntu ``` You can run the cases one by one, e.g. command diff --git a/BM/ras/bff_test.sh b/BM/ras/bff_test.sh new file mode 100755 index 00000000..9d8f471a --- /dev/null +++ b/BM/ras/bff_test.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2024 Intel Corporation +# Author: Yi Lai +# @Desc Test script to verify MCE corrected error yellow threshold status + +cd "$(dirname "$0")" 2>/dev/null || exit 1 +source ../.env +source ./ras_common.sh + +usage() { + cat <<__EOF + usage: ./${0##*/} [-t TESTCASE_ID] [-H] + -t TEST CASE ID + -H show this +__EOF +} + +bff_test() { + case $TEST_SCENARIO in + bff_yellow) + mce_config + mce_log_clear # Clear previous MCE records + + # Load mce-inject module + modprobe mce-inject || die "Failed to load mce-inject module" + + # Inject corrected-yellow MCE + mce-inject ./mce-inject/test/corrected-yellow || die "mce-inject corrected-yellow failed" + + # Verify dmesg reports machine check events + if ! dmesg | grep -q "Machine check events logged"; then + die "dmesg does not contain 'Machine check events logged'" + fi + test_print_trc "dmesg confirms machine check events logged" + + # Verify MCE log reports yellow threshold status + if ! mce_log_check "Threshold based error status: yellow"; then + die "MCE log does not contain yellow threshold status" + fi + test_print_trc "MCE log confirms yellow threshold status" + ;; + esac +} + +while getopts :t:H arg; do + case $arg in + t) + TEST_SCENARIO=$OPTARG + ;; + H) + usage && exit 0 + ;; + \?) + usage + die "Invalid Option -$OPTARG" + ;; + :) + usage + die "Option -$OPTARG requires an argument." + ;; + esac +done + +bff_test diff --git a/BM/ras/einjv2_test.sh b/BM/ras/einjv2_test.sh new file mode 100755 index 00000000..1ec19d6e --- /dev/null +++ b/BM/ras/einjv2_test.sh @@ -0,0 +1,165 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (c) 2024 Intel Corporation +# Author: Yi Lai +# @Desc Test script to verify EINJ v2 (ACPI Error Injection) CE memory error injection + +cd "$(dirname "$0")" 2>/dev/null || exit 1 +source ../.env + +LOG="${PWD}/dmesg_einjv2.log" +tmp_addr_file="${PWD}/einj_v2.txt" +iomem_tmp="${PWD}/iomem_v2_tmp" + +PAGESIZE=4096 +NUM_TESTADDR=20 +RANGE_SIZE_THR_MB=500 +EINJ_DIR="/sys/kernel/debug/apei/einj" + +cleanup() { rm -f "$tmp_addr_file" "$iomem_tmp" || true; } +trap cleanup EXIT + +usage() { + cat <<__EOF + usage: ./${0##*/} [-t TESTCASE_ID] [-H] + -t TEST CASE ID + -H show this +__EOF +} + +# Generate test addresses from System RAM ranges +generate_test_addresses() { + [[ -f "$LOG" ]] && rm -f "$LOG" + : >"$tmp_addr_file" + + local URANDOM + URANDOM=$(od -An -N4 -t uL /dev/urandom | tr -d " ") + + grep -E "System RAM" /proc/iomem | cut -d ':' -f1 >"$iomem_tmp" + test_print_trc "Generating test addresses from System RAM ranges" + + while read -r line; do + local start_addr end_addr rand_addr test_pfn_base test_pfn test_addr + start_addr=$((16#$(echo "$line" | awk -F '-' '{print $1}'))) + end_addr=$((16#$(echo "$line" | awk -F '-' '{print $2}'))) + + # skip address < 1MB + ((start_addr < 0x100000)) && continue + # skip small memory areas (<500MB) + (((end_addr - start_addr) < (RANGE_SIZE_THR_MB * 0x100000))) && continue + + rand_addr=$((start_addr + URANDOM % (end_addr - start_addr))) + if ((rand_addr + NUM_TESTADDR * PAGESIZE > end_addr)); then + rand_addr=$start_addr + fi + + test_pfn_base=$((rand_addr / PAGESIZE)) + for ((i = 1; i <= NUM_TESTADDR; i++)); do + test_pfn=$((test_pfn_base + i)) + test_addr=$((test_pfn * PAGESIZE)) + ((test_addr > end_addr)) && break + printf "0x%lx\n" "$test_addr" >>"$tmp_addr_file" + done + done <"$iomem_tmp" + + [[ -s "$tmp_addr_file" ]] || die "No valid test addresses generated" +} + +# Prepare EINJv2 interface +prepare_einj_v2() { + if [[ ! -d "$EINJ_DIR" ]]; then + mountpoint -q /sys/kernel/debug || mount -t debugfs debugfs /sys/kernel/debug || true + fi + [[ -d "$EINJ_DIR" ]] || die "EINJv2 interface not available at $EINJ_DIR" + + pushd "$EINJ_DIR" >/dev/null || die "Failed to pushd to $EINJ_DIR" + [[ -r available_error_type ]] || die "EINJv2 'available_error_type' not readable" + + if grep -qw "V2_0x00000002" available_error_type; then + echo "V2_0x00000002" >error_type + else + popd >/dev/null || return + die "Required EINJv2 error type 'V2_0x00000002' not available" + fi + + # Configure EINJ v2 parameters + [[ -w param2 ]] && echo 0xfffffffffffff000 >param2 + [[ -w component_id0 ]] && echo 0x1 >component_id0 + [[ -w component_syndrome0 ]] && echo 0x4 >component_syndrome0 + [[ -w component_id1 ]] && echo 0x2 >component_id1 + [[ -w component_syndrome1 ]] && echo 0x4 >component_syndrome1 + [[ -w flags ]] && echo 0xa >flags + [[ -w notrigger ]] && echo 0 >notrigger + popd >/dev/null || return +} + +# Inject errors and verify SystemAddress in dmesg +inject_and_verify() { + pushd "$EINJ_DIR" >/dev/null || die "Failed to pushd to $EINJ_DIR" + + while read -r addr; do + local iter_marker output sys_addr + iter_marker="EINJ_V2_MARKER_${addr}_$(date +%s%N)" + if [[ -w /dev/kmsg ]]; then + echo "$iter_marker" >/dev/kmsg + fi + + echo "$addr" >param1 + echo 1 >error_inject + sleep 1 + + if [[ -w /dev/kmsg ]]; then + output=$(dmesg | sed -n "/$iter_marker/,\$p" | grep -v "$iter_marker" || true) + else + output=$(dmesg | tail -n 20) + fi + echo "$output" >>"$LOG" + + sys_addr=$(echo "$output" | grep -Eo "SystemAddress:0x[0-9a-fA-F]+" | head -n 1 | cut -d: -f2 || true) + + if [[ -n "$sys_addr" ]]; then + if ((addr != sys_addr)); then + popd >/dev/null || return + die "Address mismatch: injected $addr, reported $sys_addr" + fi + test_print_trc "Injected $addr matched dmesg SystemAddress" + else + popd >/dev/null || return + die "No SystemAddress found in dmesg for injected address $addr" + fi + done <"$tmp_addr_file" + + popd >/dev/null || return + test_print_trc "All EINJv2 injections verified successfully" +} + +einjv2_test() { + case $TEST_SCENARIO in + einjv2_memory) + generate_test_addresses + prepare_einj_v2 + inject_and_verify + ;; + esac +} + +while getopts :t:H arg; do + case $arg in + t) + TEST_SCENARIO=$OPTARG + ;; + H) + usage && exit 0 + ;; + \?) + usage + die "Invalid Option -$OPTARG" + ;; + :) + usage + die "Option -$OPTARG requires an argument." + ;; + esac +done + +einjv2_test diff --git a/BM/ras/lmce_test.sh b/BM/ras/lmce_test.sh index 637c60ca..32da1118 100755 --- a/BM/ras/lmce_test.sh +++ b/BM/ras/lmce_test.sh @@ -29,7 +29,7 @@ lmce_support_check() { lmce_check_result() { local testcase=$1 - if [[ $2 -eq 0 ]] && grep -q LMCE ${MCELOG_LOGFILE}; then + if [[ $2 -eq 0 ]] && mce_log_check "LMCE"; then test_print_trc "${testcase} Test PASS" else die "${testcase} Test FAIL" @@ -38,8 +38,8 @@ lmce_check_result() { lmce_test() { disable_cmci # disable MCE CMCI before LMCE test execution - cat /dev/null > ${MCELOG_LOGFILE} # clear previous decoded MCE event records - cd ras-tools/ + mce_log_clear # clear previous decoded MCE event records + cd ras-tools/ || die "Failed to cd to ras-tools/" case $TEST_SCENARIO in sameaddr_samecore_instr/instr) ./lmce -a -c 1 -t INSTR/INSTR @@ -120,5 +120,5 @@ while getopts :t:H arg; do done lmce_support_check # check whether LMCE feature is supported -mcelog_config # configure mcelog service +mce_config # configure MCE logging backend lmce_test diff --git a/BM/ras/mce_test.sh b/BM/ras/mce_test.sh index 974c98b6..c7a4028e 100755 --- a/BM/ras/mce_test.sh +++ b/BM/ras/mce_test.sh @@ -27,47 +27,51 @@ mce_check_result() { } load_edac_driver() { - for i in $(find /lib/modules/$(uname -r) -type f | grep edac); do - filename=${i##*/} - edac_driver=${filename%.ko.xz} - modprobe $edac_driver - done + get_cpu_model + case $FML in + 13) + modprobe imh_edac 2>/dev/null + ;; + *) + modprobe i10nm_edac 2>/dev/null + ;; + esac } mce_test() { case $TEST_SCENARIO in apei-inj) load_edac_driver - cd mce-test/cases/function/apei-inj/ + cd mce-test/cases/function/apei-inj/ || die "Failed to cd" bash runtest.sh ;; core_recovery_ifu) - cd mce-test/cases/function/core_recovery/ + cd mce-test/cases/function/core_recovery/ || die "Failed to cd" bash runtest_ifu.sh ;; core_recovery_dcu) - cd mce-test/cases/function/core_recovery/ + cd mce-test/cases/function/core_recovery/ || die "Failed to cd" bash runtest_dcu.sh ;; edac) - cd mce-test/cases/function/edac/ + cd mce-test/cases/function/edac/ || die "Failed to cd" bash runtest.sh ;; einj-ext) load_edac_driver - cd mce-test/cases/function/einj-ext/ + cd mce-test/cases/function/einj-ext/ || die "Failed to cd" bash runtest.sh ;; emca-inj) - cd mce-test/cases/function/emca-inj/ + cd mce-test/cases/function/emca-inj/ || die "Failed to cd" bash runtest.sh ;; erst-inject) - cd mce-test/cases/function/erst-inject/ + cd mce-test/cases/function/erst-inject/ || die "Failed to cd" bash runtest.sh ;; pfa) - cd mce-test/cases/function/pfa/ + cd mce-test/cases/function/pfa/ || die "Failed to cd" bash runtest.sh ;; esac diff --git a/BM/ras/ras_common.sh b/BM/ras/ras_common.sh index 982032f3..edef4fb4 100755 --- a/BM/ras/ras_common.sh +++ b/BM/ras/ras_common.sh @@ -10,37 +10,109 @@ source ../.env MCELOG_LOGFILE=/var/log/mcelog MCA_BANK_NUM=$((0x$(rdmsr 0x179) & 0xFF)) # 0x179 is IA32_MCG_CAP IA32_MCi_CTL2=$(rdmsr 0x280) # 0x280 is IA32_MCi_CTL2 +RASDAEMON_DB="" -# check mcelog service is properly configured and running -mcelog_config() { - local daemon=0 - local logfile=0 +# Detect rasdaemon DB path from the running process +detect_rasdaemon_db() { + [ -n "$RASDAEMON_DB" ] && return - pgrep -x mcelog >/dev/null 2>&1 - if [ $? -ne 0 ]; then - test_print_trc "mcelog service is not running, start the service" - /usr/sbin/mcelog --ignorenodev --daemon --logfile=${MCELOG_LOGFILE} - exit 0 + local pid + pid=$(pgrep -x rasdaemon) + if [ -n "$pid" ]; then + RASDAEMON_DB=$(ls -l /proc/"$pid"/fd 2>/dev/null | grep -m1 'ras-mc_event.db' | awk '{print $NF}') fi - for i in $(pgrep -a -x mcelog); do - if [[ $i == *"--daemon"* ]]; then - daemon=1 - elif [[ $i == *"--logfile=${MCELOG_LOGFILE}"* ]]; then - logfile=1 - fi - done - if [ "$daemon" -eq 0 ] || [ "$logfile" -eq 0 ]; then - test_print_trc "mcelog service is not properly configured, reload the service." - kill -9 $(pgrep -x mcelog) - /usr/sbin/mcelog --ignorenodev --daemon --logfile=${MCELOG_LOGFILE} + + [ -n "$RASDAEMON_DB" ] || die "Cannot detect rasdaemon DB path (is rasdaemon running with --record?)" +} + +# --- MCE logging backend abstraction --- + +# Detect MCE logging backend: mcelog or rasdaemon +# Prefers rasdaemon (modern). Can be overridden by setting MCE_BACKEND env var. +detect_mce_backend() { + if [ -n "$MCE_BACKEND" ]; then + return + fi + if command -v rasdaemon &>/dev/null; then + MCE_BACKEND="rasdaemon" + elif command -v mcelog &>/dev/null; then + MCE_BACKEND="mcelog" + else + die "No MCE logging backend found (mcelog or rasdaemon)" fi } +# Ensure MCE logging daemon is running and properly configured +mce_config() { + detect_mce_backend + case $MCE_BACKEND in + mcelog) + local daemon=0 + local logfile=0 + local mcelog_bin + mcelog_bin=$(command -v mcelog) || die "mcelog not found in PATH" + + if ! pgrep -x mcelog >/dev/null 2>&1; then + test_print_trc "mcelog service is not running, start the service" + "$mcelog_bin" --ignorenodev --daemon --logfile=${MCELOG_LOGFILE} + return 0 + fi + for i in $(pgrep -a -x mcelog); do + if [[ $i == *"--daemon"* ]]; then + daemon=1 + elif [[ $i == *"--logfile=${MCELOG_LOGFILE}"* ]]; then + logfile=1 + fi + done + if [ "$daemon" -eq 0 ] || [ "$logfile" -eq 0 ]; then + test_print_trc "mcelog service is not properly configured, reload the service." + kill -9 $(pgrep -x mcelog) + "$mcelog_bin" --ignorenodev --daemon --logfile=${MCELOG_LOGFILE} + fi + ;; + rasdaemon) + if ! systemctl is-active --quiet rasdaemon; then + systemctl cat rasdaemon &>/dev/null || die "rasdaemon.service not found (run 'make install' in BM/ras/)" + test_print_trc "rasdaemon is not running, starting service" + systemctl start rasdaemon || die "Failed to start rasdaemon" + fi + detect_rasdaemon_db + test_print_trc "rasdaemon DB path: ${RASDAEMON_DB}" + ;; + esac +} + +# Clear MCE log records before test execution +mce_log_clear() { + case $MCE_BACKEND in + mcelog) + cat /dev/null > "${MCELOG_LOGFILE}" + ;; + rasdaemon) + sqlite3 "${RASDAEMON_DB}" "DELETE FROM mce_record;" 2>/dev/null + ;; + esac +} + +# Check if a pattern exists in MCE log +# Usage: mce_log_check "PATTERN" +mce_log_check() { + local pattern="$1" + case $MCE_BACKEND in + mcelog) + grep -q "$pattern" "${MCELOG_LOGFILE}" + ;; + rasdaemon) + sqlite3 "${RASDAEMON_DB}" "SELECT * FROM mce_record;" | grep -q "$pattern" + ;; + esac +} + # disable MCE CMCI disable_cmci() { for (( bank=0; bank/dev/null || which rasdaemon 2>/dev/null @ mcelog or rasdaemon is required # @other_warn: which rdmsr 2>/dev/null @ rdmsr tool is required, please install msr-tools # @other_warn: which cpuid 2>/dev/null @ cpuid tool is required, please install cpuid -# @other_warn: which mcelog 2>/dev/null @ mcelog tool is required, please install mcelog -# @other_warn: which screen 2>/dev/null @ rdmsr tool is required, please install screen +# @other_warn: which mce-inject 2>/dev/null @ mce-inject tool is required, please install mce-inject +# @other_warn: which screen 2>/dev/null @ screen tool is required, please install screen +# @other_warn: which sqlite3 2>/dev/null @ sqlite3 tool is required, please install sqlite3 and sqlite-devel # error injection test cases mce_test.sh -t apei-inj @@ -14,7 +17,6 @@ mce_test.sh -t edac mce_test.sh -t einj-ext mce_test.sh -t emca-inj mce_test.sh -t erst-inject -mce_test.sh -t pfa # LMCE test cases - three-dimensional matrix # error-injected addresses: same address vs. different address @@ -38,3 +40,9 @@ lmce_test.sh -t diffaddr_samesocket_data/data lmce_test.sh -t diffaddr_diffsocket_instr/instr lmce_test.sh -t diffaddr_diffsocket_instr/data lmce_test.sh -t diffddr_diffsocket_data/data + +# MCE corrected error threshold (yellow status) test +bff_test.sh -t bff_yellow + +# EINJ v2 error injection test cases +einjv2_test.sh -t einjv2_memory From b8c0630c654b26e6f0e9ad6972b0d866a4d4640d Mon Sep 17 00:00:00 2001 From: Hongyu Ning Date: Sun, 21 Jun 2026 19:45:08 +0800 Subject: [PATCH 3/5] BM: bump Dockerfile.build.ddt to gcc-14 and add rasdaemon build deps - Replace gcc-13 with gcc-14 (+ g++-14) and their -multilib variants so the existing gcc-multilib / g++-multilib (i386) build keeps working. Register them via update-alternatives so plain `gcc` / `g++` resolve to v14 without touching in-tree Makefiles. Required by new feature folders that need gcc >= 14. - Add bison, flex, autoconf, automake, libtool, pkg-config, libsqlite3-dev, libtraceevent-dev, python3 so ras/rasdaemon can autoreconf + ./configure --enable-sqlite3 --enable-mce ... in CI. Signed-off-by: Hongyu Ning --- BM/Dockerfile.build.ddt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/BM/Dockerfile.build.ddt b/BM/Dockerfile.build.ddt index 6f183baa..a9501078 100644 --- a/BM/Dockerfile.build.ddt +++ b/BM/Dockerfile.build.ddt @@ -13,7 +13,9 @@ RUN dpkg --add-architecture i386 RUN dpkg --print-foreign-architectures RUN \ apt-get update && \ - apt-get install gcc-13 make libelf1 gcc-multilib g++-multilib git cmake -y --no-install-recommends && \ + apt-get install gcc-14 g++-14 gcc-14-multilib g++-14-multilib make libelf1 gcc-multilib g++-multilib git cmake -y --no-install-recommends && \ + apt-get install bison flex autoconf automake libtool pkg-config libsqlite3-dev libtraceevent-dev python3 -y --no-install-recommends && \ + update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 100 --slave /usr/bin/g++ g++ /usr/bin/g++-14 && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* From 459797536abd583e8df4a9134577ecbac90c20fd Mon Sep 17 00:00:00 2001 From: Hongyu Ning Date: Sun, 21 Jun 2026 19:46:33 +0800 Subject: [PATCH 4/5] BM: add DDT_SKIP_SUBDIRS, fix build-failure detection, mount /lib/modules - Add a `DDT_SKIP_SUBDIRS` make variable consumed by the top-level build loop: subdir basenames listed in it are skipped with a clear log line. Used by `docker_make_ddt` (and the CI build_check script) to skip `tdx-compliance`, which needs a matching /lib/modules/$(uname -r)/build tree not available in the DDT container. - Fix the post-build error check: it inspected `MAKE_TOOLS_LOG` (undefined) instead of `MAKE_LKVS_LOG`, so subfolder build failures were silently treated as success. Now correctly exits 2 when any subfolder failed. - Fix the per-subdir failure path: capture rc and `cd ..` before `continue` so we don't stay in the failed subdir for the next iteration. - Mount `/lib/modules/$(uname -r)` into the `docker_clean` / `docker_make` containers (matches `docker_make_ddt`) so kernel module subdirs can resolve their build tree. - Add a `docker_clean_ddt` target mirroring `docker_make_ddt` (ubuntu:24.04 image). - Reword the success message to "All required subfolders built successfully" to reflect that some may have been skipped. Signed-off-by: Hongyu Ning --- BM/Makefile | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/BM/Makefile b/BM/Makefile index 97a3db41..63d9b63d 100644 --- a/BM/Makefile +++ b/BM/Makefile @@ -3,6 +3,8 @@ SUBDIRS = $(shell ls -d */) +DDT_SKIP_SUBDIRS ?= + PROXY := MAKE_LKVS_LOG = /tmp/make_lkvs.log @@ -19,23 +21,29 @@ endif all: @cat /dev/null > ${MAKE_LKVS_LOG}; - @for dir in $(SUBDIRS); do \ - if [ -f "$$dir/Makefile" ]; then \ - cd $$dir && \ - make || { \ + @for dir in $(SUBDIRS); do \ + base=$$(basename "$${dir%/}"); \ + if printf '%s\n' " $(DDT_SKIP_SUBDIRS) " | grep -Fq " $${base} "; then \ + echo " - SKIP: subfolder $${dir} skipped for DDT docker build."; \ + continue; \ + fi; \ + if [ -f "$$dir/Makefile" ]; then \ + cd $$dir && \ + make || { \ + rc=$$?; \ + cd ..; \ echo " - Make subfolder $${dir} failed." >> ${MAKE_LKVS_LOG}; \ - cd ..; \ - continue; \ - }; \ - cd ..; \ - fi \ + continue; \ + }; \ + cd ..; \ + fi \ done cat $(MAKE_LKVS_LOG) - @if [ -s ${MAKE_TOOLS_LOG} ]; then \ + @if [ -s ${MAKE_LKVS_LOG} ]; then \ echo "Some subfolder failed to build"; \ exit 2; \ else \ - echo "All subfolder built successfully"; \ + echo "All required subfolders built successfully"; \ exit 0; \ fi @@ -46,7 +54,10 @@ clean: fi \ done docker_clean: - docker run -it --rm -v $(PWD):/src --name ubuntu_2204_lkvs ubuntu:22.04 make clean + docker run -it --rm -v $(PWD):/src -v /lib/modules/`uname -r`:/lib/modules/`uname -r` --name ubuntu_2204_lkvs ubuntu:22.04 make clean + +docker_clean_ddt: + docker run -it --rm -v $(PWD):/src -v /lib/modules/`uname -r`:/lib/modules/`uname -r` --name ubuntu_2404_lkvs ubuntu:24.04 make clean # Target test and docker_test are for github action mainly. # It's used to do a compiling validation. @@ -69,7 +80,7 @@ docker_make: docker run -it --rm -v $(PWD):/src -v /lib/modules/`uname -r`:/lib/modules/`uname -r` --name ubuntu_2204_lkvs ubuntu:22.04 make docker_make_ddt: - docker run -it --rm -v $(PWD):/src -v /lib/modules/`uname -r`:/lib/modules/`uname -r` --name ubuntu_2404_lkvs ubuntu:24.04 make + docker run -it --rm -v $(PWD):/src -v /lib/modules/`uname -r`:/lib/modules/`uname -r` --name ubuntu_2404_lkvs ubuntu:24.04 make DDT_SKIP_SUBDIRS="tdx-compliance" build: @echo "Building $(word 2, $(MAKECMDGOALS))" From f90b47923a711c9dbeaaa980e4c4d7a62c910661 Mon Sep 17 00:00:00 2001 From: Hongyu Ning Date: Sun, 21 Jun 2026 19:30:42 +0800 Subject: [PATCH 5/5] ci: pin ubuntu-24.04, use DDT image, gate warnings via allowlist - pull_request.yml: * runs-on: ubuntu-latest -> ubuntu-24.04 (all jobs); checkout v3->v4, setup-python v4->v5. * BuildCheck: drop docker-engine bootstrap (preinstalled on the runner), drop sudo, build from BM/Dockerfile.build.ddt, checkout submodules recursively. * CodeCheck: use apt-get + set -euo pipefail, add wget. * cfg-lint-check: replace tj-actions/changed-files@v46 with an inline `git diff` over the PR merge-base feeding the cartesian matrix. - .github/scripts/build_check: * Fix bogus `set -oe pipefail` -> `set -o pipefail`. * Use a named, run-id-scoped container with a cleanup trap. * Log container os-release, gcc/g++ versions, uname before building. * Preconfigure ras/rasdaemon (autoreconf + ./configure) before `make test`; skip tdx-compliance by default via DDT_SKIP_SUBDIRS (needs a matching kernel build tree not present in CI). * Capture rc via PIPESTATUS; split warnings into build_warnings.log and unexpected_build_warnings.log, failing only on the latter. - .github/scripts/build_warning_allowlist (new): * Regex-per-line allowlist of currently known pre-existing build warnings (cet, cmpccxadd, ras/mce-test, einj, memattr, page, etc.) so CI gates on new regressions only. Entries should be pruned as the underlying source is fixed. Signed-off-by: Hongyu Ning --- .github/scripts/build_check | 134 +++++++++++++++++++++++- .github/scripts/build_warning_allowlist | 38 +++++++ .github/workflows/pull_request.yml | 119 +++++++++++++++------ BM/workload-xsave/Makefile | 12 ++- 4 files changed, 267 insertions(+), 36 deletions(-) create mode 100644 .github/scripts/build_warning_allowlist diff --git a/.github/scripts/build_check b/.github/scripts/build_check index 7625ed7e..edf456f3 100755 --- a/.github/scripts/build_check +++ b/.github/scripts/build_check @@ -1,16 +1,140 @@ #!/usr/bin/env bash # SPDX-License-Identifier: GPL-2.0-only -set -oe pipefail +set -o pipefail wpattern=" warning: " logfile="build.log" +warnings_file="build_warnings.log" +unexpected_warnings_file="unexpected_build_warnings.log" +allowlist_file=".github/scripts/build_warning_allowlist" -docker run -v "$(pwd)"/BM:/src builder make test | tee "$logfile" +repo_root="$(git rev-parse --show-toplevel 2>/dev/null || pwd)" +bm_dir="${repo_root}/BM" +container_name="lkvs-build-check-${GITHUB_RUN_ID:-manual}-${GITHUB_RUN_ATTEMPT:-0}" + +# tdx-compliance builds a kernel module and requires a matching +# /lib/modules/$(uname -r)/build tree, which is not available/matched in +# the CI docker environment. Keep workload-xsave covered by CI. +ci_skip_subdirs="${DDT_SKIP_SUBDIRS:-tdx-compliance}" + +cleanup_container() +{ + docker rm -f "$container_name" >/dev/null 2>&1 || true +} + +rm -f "$logfile" "$warnings_file" "$unexpected_warnings_file" +cleanup_container +trap cleanup_container EXIT + +echo "===== Build check configuration =====" +echo "repo_root=${repo_root}" +echo "bm_dir=${bm_dir}" +echo "container_name=${container_name}" +echo "DDT_SKIP_SUBDIRS=${ci_skip_subdirs}" +echo "=====================================" + +echo "===== Docker build environment info =====" +docker run --rm \ + -v "${bm_dir}":/src \ + -w /src \ + builder \ + sh -c ' + echo "Container userspace:" + cat /etc/os-release 2>/dev/null || true + + echo + echo "Toolchain versions:" + gcc --version 2>/dev/null | head -n 1 || true + g++ --version 2>/dev/null | head -n 1 || true + + echo + echo "uname before BM test target copies fake uname:" + command -v uname || true + uname -a || true + uname -r || true + + echo + echo "Available kernel module build directories:" + ls -ld /lib/modules/*/build 2>/dev/null || true + + echo + echo "Fake uname shipped in image, if present:" + ls -l /usr/local/uname 2>/dev/null || true + ' || true +echo "=========================================" + +echo "===== Preconfigure rasdaemon in a smaller Docker run =====" +docker run --rm \ + -v "${bm_dir}":/src \ + -w /src \ + builder \ + sh -c ' + set -e + cd /src/ras/rasdaemon + + if [ ! -x ./configure ]; then + autoreconf -i + fi + + if [ ! -f ./Makefile ]; then + ./configure --enable-sqlite3 --enable-mce \ + --enable-extlog --enable-memory-failure --enable-memory-ce-pfa + fi + ' + +preconfigure_rc=$? +if [ "$preconfigure_rc" -ne 0 ]; then + echo "===========================================" + echo "rasdaemon preconfigure failed with rc=${preconfigure_rc}" + echo "===========================================" + exit "$preconfigure_rc" +fi + +echo "===== Start build in named container =====" +docker run \ + --name "$container_name" \ + -v "${bm_dir}":/src \ + -w /src \ + builder \ + make DDT_SKIP_SUBDIRS="${ci_skip_subdirs}" test 2>&1 | tee "$logfile" + +docker_rc=${PIPESTATUS[0]} + +if [ "$docker_rc" -ne 0 ]; then + echo "===========================================" + echo "docker build container failed with rc=${docker_rc}" + echo "===========================================" + exit "$docker_rc" +fi + +grep "$wpattern" "$logfile" > "$warnings_file" || true + +if [ -s "$warnings_file" ]; then + if [ -f "$allowlist_file" ]; then + grep -Ev -f "$allowlist_file" "$warnings_file" > "$unexpected_warnings_file" || true + else + cp "$warnings_file" "$unexpected_warnings_file" + fi + + if [ -s "$unexpected_warnings_file" ]; then + echo "===========================================" + echo "There are unexpected build warning(s), fix required!" + echo "===========================================" + cat "$unexpected_warnings_file" + exit 1 + fi -if grep "$wpattern" "$logfile"; then echo "===========================================" - echo "There are build warning(s), fix required!" + echo "Only known/allowed build warning(s) found." + echo "Allowed warnings count: $(wc -l < "$warnings_file")" + echo "===========================================" +else + echo "===========================================" + echo "No build warnings found." echo "===========================================" - false fi + +echo "===========================================" +echo "Build check passed." +echo "===========================================" diff --git a/.github/scripts/build_warning_allowlist b/.github/scripts/build_warning_allowlist new file mode 100644 index 00000000..ccab7435 --- /dev/null +++ b/.github/scripts/build_warning_allowlist @@ -0,0 +1,38 @@ +^wrss\.c:31: warning: "SHADOW_STACK_SET_TOKEN" redefined +^shstk_unlock_test\.c:35: warning: "SHADOW_STACK_SET_TOKEN" redefined +^shstk_cp\.c:28: warning: "SHADOW_STACK_SET_TOKEN" redefined +^glibc_shstk_test\.c:154:9: warning: 'memset' writing 44 bytes into a region of size 20 overflows the destination +^glibc_shstk_test\.c:167:9: warning: 'memset' writing 28 bytes into a region of size 20 overflows the destination + +^cmpccxadd\.c:70:16: warning: format '%d' expects argument of type 'int', but argument [0-9]+ has type 'long unsigned int' +^cmpccxadd\.c:85:16: warning: format '%d' expects argument of type 'int', but argument [0-9]+ has type 'long unsigned int' +^cmpccxadd\.c:101:16: warning: format '%d' expects argument of type 'int', but argument [0-9]+ has type 'long int' +^cmpccxadd\.c:116:16: warning: format '%d' expects argument of type 'int', but argument [0-9]+ has type 'long int' +^cmpccxadd\.c:147:[0-9]+: warning: format '%d' expects argument of type 'int', but argument [0-9]+ has type 'long unsigned int' +^cmpccxadd\.c:162:[0-9]+: warning: format '%d' expects argument of type 'int', but argument [0-9]+ has type 'long int' + +^sort_test\.c:55:42: warning: format '%zu' expects argument of type 'size_t', but argument 2 has type 'int' +^ltp-pan\.c:433:15: warning: variable 'av' set but not used +^victim\.c:57:13: warning: variable 'fatarray' set but not used +^erst-inject\.c:137:34: warning: variable 'mem_err' set but not used +^/usr/include/features\.h:196:3: warning: #warning "_BSD_SOURCE and _SVID_SOURCE are deprecated, use _DEFAULT_SOURCE" + +^tinjpage\.c:824:36: warning: '%s' directive output may be truncated writing up to 255 bytes into a region of size 100 +^tinjpage\.c:230:35: warning: 'fclose' called on pointer returned from a mismatched allocation function +^tsoftinj\.c:149:38: warning: '%s' directive output may be truncated writing up to 255 bytes into a region of size 100 +^page-poisoning\.c:399:44: warning: '/dirty' directive output may be truncated writing 6 bytes into a region of size between 1 and 4096 +^page-poisoning\.c:469:35: warning: '/clean' directive output may be truncated writing 6 bytes into a region of size between 1 and 4096 + +^einj\.c:168:45: warning: format '%x' expects argument of type 'unsigned int', but argument 4 has type 'long long unsigned int' +^einj_mem_uc\.c:985:17: warning: ignoring return value of 'fscanf' declared with attribute 'warn_unused_result' +^proc_cpuinfo\.c:52:64: warning: format '%d' expects argument of type 'int', but argument 3 has type 'long int' +^/usr/bin/ld: warning: do_memcpy\.o: missing \.note\.GNU-stack section implies executable stack + +^memattr\.c:138:40: warning: format '%ld' expects argument of type 'long int', but argument 2 has type 'int' +^memattr\.c:138:63: warning: format '%d' expects argument of type 'int', but argument 4 has type 'long unsigned int' +^memattr\.c:138:68: warning: format '%d' expects argument of type 'int', but argument 5 has type 'long unsigned int' +^victim\.c:347:17: warning: ignoring return value of 'read' declared with attribute 'warn_unused_result' + +^page\.c:382:25: warning: ignoring return value of 'asprintf' declared with attribute 'warn_unused_result' +^page\.c:389:25: warning: ignoring return value of 'asprintf' declared with attribute 'warn_unused_result' +^page\.c:400:25: warning: ignoring return value of 'asprintf' declared with attribute 'warn_unused_result' diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index c798e354..7864c8bc 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -11,11 +11,16 @@ on: jobs: CodeCheck: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Setup Environment + shell: bash run: | - sudo apt install -y python3 python3-pip python3-git python3-ply git shellcheck perl codespell + set -euo pipefail + + sudo apt-get update + sudo apt-get install -y python3 python3-pip python3-git python3-ply git shellcheck perl codespell wget + sudo mkdir -p /usr/share/codespell sudo wget https://raw.githubusercontent.com/codespell-project/codespell/master/codespell_lib/data/dictionary.txt -O /usr/share/codespell/dictionary.txt sudo wget https://raw.githubusercontent.com/torvalds/linux/master/scripts/spelling.txt -O /usr/bin/spelling.txt @@ -23,37 +28,50 @@ jobs: sudo wget https://raw.githubusercontent.com/torvalds/linux/master/scripts/checkpatch.pl -O /bin/checkpatch.pl sudo chmod +x /bin/checkpatch.pl - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Check Code run: | git config --global --add safe.directory "$GITHUB_WORKSPACE" ./.github/scripts/pr_check "origin/${{ github.base_ref }}" "${{ github.sha }}" + BuildCheck: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - - name: Setup Environment + - name: Show runner info + shell: bash run: | - sudo apt remove docker docker-engine docker.io containerd runc -y - sudo apt install ca-certificates curl gnupg lsb-release -y - sudo mkdir -p /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - sudo apt update - sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y + set -euo pipefail + + echo "===== GitHub runner context =====" + echo "Runner OS: ${RUNNER_OS:-unknown}" + echo "Runner arch: ${RUNNER_ARCH:-unknown}" + echo "GitHub ref: ${GITHUB_REF:-unknown}" + echo "GitHub SHA: ${GITHUB_SHA:-unknown}" + + echo "===== /etc/os-release =====" + cat /etc/os-release || true + + echo "===== uname =====" + uname -a || true + + echo "===== docker =====" + docker --version + docker info >/dev/null && echo "Docker daemon is ready." - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 + submodules: recursive - name: Build Docker Image - run: sudo docker build -f BM/Dockerfile.build -t builder BM + run: docker build -f BM/Dockerfile.build.ddt -t builder BM - name: Build Project - run: sudo ./.github/scripts/build_check + run: ./.github/scripts/build_check + python-style-check: name: Python ${{ matrix.python-version }} - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 strategy: matrix: @@ -62,11 +80,11 @@ jobs: steps: - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -76,33 +94,74 @@ jobs: - name: Run inspekt run: inspekt checkall ./KVM --disable-style E501,E265,W601,E402,E722,E741 --disable-lint=W,R,C,E0601,E1002,E1101,E1103,E1120,F0401,I0011,I1101 --enable-lint W0611,W1201 --no-license-check - run: echo "This job's status is ${{ job.status }}." + cfg-lint-check: name: Cfg lint - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Get changed files + - name: Get changed cfg files id: cfg-files - uses: tj-actions/changed-files@v46 - with: - files: | - ./KVM/qemu/*.cfg + shell: bash + run: | + set -euo pipefail + + BASE="${{ github.event.pull_request.base.sha }}" + HEAD="${{ github.event.pull_request.head.sha }}" + MERGE_BASE="$(git merge-base "${BASE}" "${HEAD}")" + + echo "Base SHA: ${BASE}" + echo "Head SHA: ${HEAD}" + echo "Merge base: ${MERGE_BASE}" + + # Include added, copied, modified, renamed, and type-changed cfg files; exclude deleted files. + git diff --name-only --diff-filter=ACMRT "${MERGE_BASE}" "${HEAD}" -- 'KVM/qemu/*.cfg' > changed_cfg_files.txt + + echo "Changed cfg files:" + cat changed_cfg_files.txt || true + + { + echo "all_changed_files<> "$GITHUB_OUTPUT" + + if [ -s changed_cfg_files.txt ]; then + echo "any_changed=true" >> "$GITHUB_OUTPUT" + else + echo "any_changed=false" >> "$GITHUB_OUTPUT" + fi - name: Set matrix id: set-matrix - run: echo matrix=$(python3 -c 'print("${{ steps.cfg-files.outputs.all_changed_files }}".split())') >> $GITHUB_OUTPUT + shell: bash + run: | + python3 - <<'PY' >> "$GITHUB_OUTPUT" + import json + + with open("changed_cfg_files.txt", "r", encoding="utf-8") as f: + files = [line.strip() for line in f if line.strip()] + + print(f"matrix={json.dumps(files)}") + PY - name: Check cfg files lint if: steps.cfg-files.outputs.any_changed == 'true' + shell: bash run: | - ./.github/scripts/cfg-lint-check.py ${{ steps.cfg-files.outputs.all_changed_files }} + set -euo pipefail + mapfile -t cfg_files < changed_cfg_files.txt + echo "Linting cfg files:" + printf ' %s\n' "${cfg_files[@]}" + ./.github/scripts/cfg-lint-check.py "${cfg_files[@]}" + cartesian-syntax-check: name: Cartesian syntax - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 needs: cfg-lint-check if: ${{ needs.cfg-lint-check.outputs.matrix != '[]' }} strategy: @@ -112,7 +171,7 @@ jobs: steps: - name: Check out repository code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Parse ${{ matrix.file }} into Cartesian configuration diff --git a/BM/workload-xsave/Makefile b/BM/workload-xsave/Makefile index 8a1acfaa..b0e8f95f 100644 --- a/BM/workload-xsave/Makefile +++ b/BM/workload-xsave/Makefile @@ -22,7 +22,6 @@ OBJS= yogini.o work_AMX.o work_AVX.o work_AVX2.o work_AVX512.o work_VNNI512.o $( ASMS= work_AMX.S work_AVX.S work_AVX2.S work_AVX512.S work_VNNI512.S work_VNNI.S work_DOTPROD.S work_PAUSE.S work_TPAUSE.S work_UMWAIT.S work_RDTSC.S work_SSE.S work_MEM.S work_memcpy.S GCC11_OBJS=work_VNNI.o -yogini : $(OBJS) $(ASMS) ifeq ($(DEBUG), 1) override CFLAGS += -march=sapphirerapids -g else @@ -35,6 +34,17 @@ override CFLAGS += -mtune=skylake-avx512 #override CFLAGS += -mtune=alderlake override CFLAGS += -mavx512bf16 +# work_AMX.c uses AMX tile intrinsics such as _tile_loadconfig(), which +# require AMX target options at compile time. Do not rely on -march=native +# because it depends on host CPU features exposed to the container and may +# otherwise fail with "target specific option mismatch" +AMX_CFLAGS := -mamx-tile -mamx-bf16 + +work_AMX.o: CFLAGS += $(AMX_CFLAGS) +work_AMX.S: CFLAGS += $(AMX_CFLAGS) + +yogini : $(OBJS) $(ASMS) + LDFLAGS += -lm LDFLAGS += -lpthread