Skip to content

Migrate virtio-net from semu #4542

Migrate virtio-net from semu

Migrate virtio-net from semu #4542

Workflow file for this run

name: CI
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
detect-code-related-file-changes:
runs-on: ubuntu-24.04
outputs:
has_code_related_changes: ${{ steps.changed-files.outputs.any_changed }}
steps:
- name: Check out the repo
uses: actions/checkout@v7
- name: Test changed files
id: changed-files
uses: tj-actions/changed-files@v47
with:
files: |
.ci/**
.github/actions/**
.github/workflows/**
build/**
configs/**
mk/**
scripts/**
src/**
tests/**
tools/**
.clang-format
Dockerfile
Makefile
# Emscripten output is platform independent, so it is built once on x64
# rather than in every host matrix leg.
wasm-build:
name: emcc build
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 30
runs-on: ubuntu-24.04
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v7
with:
submodules: 'true'
- name: Set up build environment
uses: ./.github/actions/setup-build
with:
llvm: 'false'
# No artifact prefetch: the build steps below open with "make
# distclean", which would throw away anything downloaded here.
- name: Set up emsdk
uses: mymindstorm/setup-emsdk@v16
with:
version: 3.1.51
actions-cache-folder: 'emsdk-cache'
# Note: wasm_defconfig sets CONFIG_BUILD_WASM=y which auto-selects CC=emcc
- name: Build user emulation
run: |
make distclean
make wasm_defconfig
.ci/emsdk-warm-cache.sh
make $PARALLEL
- name: Build system emulation
run: |
make distclean
make wasm_defconfig
make ENABLE_SYSTEM=1 ENABLE_GOLDFISH_RTC=1 $PARALLEL
host-x64:
name: x64 ${{ matrix.compiler }}
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
compiler: [gcc, clang]
runs-on: ubuntu-24.04
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v7
with:
submodules: 'true'
- name: Set up build environment
id: setup
uses: ./.github/actions/setup-build
with:
compiler: ${{ matrix.compiler }}
riscv-toolchain: 'true'
artifacts: elf linux-image doom
cache-suffix: host-${{ matrix.compiler }}
- name: Build with various optimization levels
run: .ci/build-opt-levels.sh defconfig
- name: Build system emulation with various optimization levels
run: .ci/build-opt-levels.sh system_defconfig
- name: check + tests
run: |
make cleanconfig
make defconfig
make check $PARALLEL
make tests $PARALLEL
make misalign $PARALLEL
make tool $PARALLEL
- name: SDL disable test
run: |
# SDL is the graphics subsystem; an interpreter-only test suffices.
make distclean && make defconfig && make ENABLE_SDL=0 check $PARALLEL
- name: misalignment test in block emulation
run: |
make -C tests/system/alignment/
make distclean && make system_defconfig && make ENABLE_ELF_LOADER=1 ENABLE_EXT_C=0 misalign-in-blk-emu $PARALLEL
- name: MMU test
run: |
make -C tests/system/mmu/
make distclean && make system_defconfig && make ENABLE_ELF_LOADER=1 mmu-test $PARALLEL
- name: gdbstub test
run: make distclean && make defconfig && make ENABLE_GDBSTUB=1 gdbstub-test $PARALLEL
- name: JIT base test
run: make distclean && make jit_defconfig && make check $PARALLEL
- name: undefined behavior test
if: success() || failure()
run: |
make distclean && make defconfig && make ENABLE_UBSAN=1 check $PARALLEL
make distclean && make jit_defconfig && make ENABLE_UBSAN=1 check $PARALLEL
# Each optional feature is independently switchable, so every one of them is
# built with the knob off. Split across runners because the serial run of all
# 24 builds dominated the job it used to live in.
host-x64-feature-disable:
name: x64 ${{ matrix.compiler }} feature disable (${{ matrix.group }})
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
compiler: [gcc, clang]
group: [core, bitmanip-perf] # .ci/test-ext-disable.sh owns the members
runs-on: ubuntu-24.04
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v7
with:
submodules: 'true'
- name: Set up build environment
id: setup
uses: ./.github/actions/setup-build
with:
compiler: ${{ matrix.compiler }}
riscv-toolchain: 'true'
artifacts: elf
cache-suffix: feature-${{ matrix.compiler }}-${{ matrix.group }}
- name: Feature disable tests (interpreter + JIT)
run: .ci/test-ext-disable.sh ${{ matrix.group }}
# The architecture test is compiler agnostic: it validates the emulator
# against the Sail model, so a second host compiler adds runtime, not
# coverage. It is x64 only, since the macOS runners are the scarcest
# resource in this workflow and provide nothing the Linux run does not.
arch-test-x64:
name: RISC-V architecture test
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 45
runs-on: ubuntu-24.04
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v7
with:
submodules: 'true'
- name: Set up build environment
id: setup
uses: ./.github/actions/setup-build
with:
compiler: gcc
llvm: 'false'
riscv-toolchain: 'true'
# No artifact prefetch: riscv-tests.sh starts with "make distclean",
# so anything cached under build/ would be thrown away unread.
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: '3.12'
cache: 'pip'
cache-dependency-path: .ci/requirements.txt
- name: Architecture test
run: .ci/riscv-tests.sh
# Boot tests are the long pole of the workflow, so each configuration gets
# its own runner. T2C is clang only because it goes through LLVM.
boot-tests-x64:
name: x64 ${{ matrix.compiler }} boot (${{ matrix.boot_type }})
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 40 # T2C boot ~30min + build ~3min + setup ~3min
strategy:
fail-fast: false
matrix:
include:
- compiler: gcc
boot_type: interpreter
defconfig: system_defconfig
make_flags: ""
timeout: 60
- compiler: gcc
boot_type: jit
defconfig: system_defconfig
make_flags: "ENABLE_JIT=1 ENABLE_MOP_FUSION=0"
timeout: 120
- compiler: clang
boot_type: interpreter
defconfig: system_defconfig
make_flags: ""
timeout: 60
- compiler: clang
boot_type: jit
defconfig: system_defconfig
make_flags: "ENABLE_JIT=1 ENABLE_MOP_FUSION=0"
timeout: 120
- compiler: clang
boot_type: t2c
defconfig: system_jit_defconfig
make_flags: "ENABLE_MOP_FUSION=0"
timeout: 150
runs-on: ubuntu-24.04
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v7
with:
submodules: 'true'
- name: Set up build environment
id: setup
uses: ./.github/actions/setup-build
with:
compiler: ${{ matrix.compiler }}
llvm: ${{ matrix.compiler == 'clang' }}
artifacts: linux-image
cache-suffix: boot-${{ matrix.compiler }}-${{ matrix.boot_type }}
- name: boot Linux kernel test (${{ matrix.boot_type }})
env:
BOOT_TIMEOUT: ${{ matrix.timeout }}
run: |
# A stale object would mask a failed LLVM detection below.
rm -f build/t2c.o
make distclean && make ${{ matrix.defconfig }} && make INITRD_SIZE=32 ${{ matrix.make_flags }} $PARALLEL && make artifact $PARALLEL
if [ "${{ matrix.boot_type }}" = "t2c" ]; then
test -f build/t2c.o || { echo "ERROR: T2C disabled (build/t2c.o missing) - LLVM $(cat .ci/llvm-version) detection failed"; exit 1; }
fi
.ci/boot-linux-test.sh
# Native AArch64 on GitHub ARM runners - fast, no QEMU overhead
# FIXME: gcc build fails on AArch64/Linux hosts, hence clang only
host-arm64:
name: arm64 clang
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 45
runs-on: ubuntu-24.04-arm
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: checkout code
uses: actions/checkout@v7
with:
submodules: 'true'
- name: Set up build environment
id: setup
uses: ./.github/actions/setup-build
with:
# Plain "clang" resolves through the LLVM bin directory this action
# prepends to PATH, so it is the pinned LLVM, not the distro's.
cc: clang
artifacts: elf linux-image
cache-suffix: host
- name: check + tests
run: |
make cleanconfig
make defconfig
make check $PARALLEL
- name: JIT tests
run: |
set -euo pipefail
make distclean && make jit_defconfig && make check $PARALLEL
for ext in ENABLE_EXT_A ENABLE_EXT_F ENABLE_EXT_C; do
echo "JIT test with ${ext}=0"
make ENABLE_JIT=1 clean && make ${ext}=0 ENABLE_JIT=1 check $PARALLEL
done
- name: boot Linux kernel test (T2C)
env:
BOOT_TIMEOUT: 120 # T2C with O1 optimization (via defconfig) is faster than O3
run: |
# A stale object would mask a failed LLVM detection below.
rm -f build/t2c.o
# system_jit_defconfig uses T2C_OPT_LEVEL=1 for ~50% faster LLVM compilation
make distclean && make system_jit_defconfig && make INITRD_SIZE=32 ENABLE_MOP_FUSION=0 $PARALLEL && make artifact $PARALLEL
test -f build/t2c.o || { echo "ERROR: T2C disabled (build/t2c.o missing) - LLVM ${{ steps.setup.outputs.llvm-version }} detection failed"; exit 1; }
.ci/boot-linux-test.sh
macOS-arm64:
name: macOS ${{ matrix.compiler }}
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
compiler: [gcc-15, clang]
runs-on: macos-latest # M1 chip
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v7
with:
submodules: 'true'
- name: Set up build environment
id: setup
uses: ./.github/actions/setup-build
with:
compiler: ${{ matrix.compiler }}
riscv-toolchain: 'true'
artifacts: elf linux-image doom
cache-suffix: host-${{ matrix.compiler }}
- name: check + tests
run: |
make cleanconfig
make defconfig
make check $PARALLEL
make tests $PARALLEL
make misalign $PARALLEL
make tool $PARALLEL
- name: SDL disable test
run: |
# SDL is the graphics subsystem; an interpreter-only test suffices.
make distclean && make defconfig && make ENABLE_SDL=0 check $PARALLEL
- name: gdbstub test, need RV32 toolchain
run: make distclean && make defconfig && make ENABLE_GDBSTUB=1 gdbstub-test $PARALLEL
- name: JIT base test
run: make distclean && make jit_defconfig && make check $PARALLEL
- name: undefined behavior test
# gcc on macOS/arm64 does not support sanitizers
if: (success() || failure()) && matrix.compiler == 'clang'
run: |
make distclean && make defconfig && make ENABLE_UBSAN=1 check $PARALLEL
make distclean && make jit_defconfig && make ENABLE_UBSAN=1 check $PARALLEL
- name: boot Linux kernel test
run: |
make distclean && make system_defconfig && make INITRD_SIZE=32 $PARALLEL && make artifact $PARALLEL
.ci/boot-linux-test.sh
make clean
- name: boot Linux kernel test (JIT)
env:
BOOT_TIMEOUT: 120 # JIT under macOS load has flaked at 90s
run: |
make distclean && make system_defconfig && make INITRD_SIZE=32 ENABLE_JIT=1 ENABLE_MOP_FUSION=0 $PARALLEL && make artifact $PARALLEL
.ci/boot-linux-test.sh
make clean
macOS-arm64-feature-disable:
name: macOS ${{ matrix.compiler }} feature disable
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
compiler: [gcc-15, clang]
runs-on: macos-latest
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v7
with:
submodules: 'true'
- name: Set up build environment
id: setup
uses: ./.github/actions/setup-build
with:
compiler: ${{ matrix.compiler }}
riscv-toolchain: 'true'
artifacts: elf
cache-suffix: feature-${{ matrix.compiler }}
- name: Feature disable tests (interpreter + JIT)
run: .ci/test-ext-disable.sh
coding-style:
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 15
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: Install formatters
run: .ci/install-formatters.sh
- name: coding convention
run: |
.ci/check-newline.sh
.ci/check-format.sh
static-analysis:
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 45
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
with:
submodules: 'true'
# scan-build lives in clang-tools-<N>, and the analyzer resolves the
# versioned clang-<N>/scan-build-<N> names from /usr/bin. Those are apt
# symlinks outside /usr/lib/llvm-<N>, so the LLVM cache the other jobs use
# would restore the tree without the names this job calls: install fresh.
- name: Set up scan-build
run: |
LLVM_VERSION=$(cat .ci/llvm-version)
.ci/apt-install.sh curl wget lsb-release gnupg libsdl2-dev libsdl2-mixer-dev
sudo .ci/install-llvm.sh "${LLVM_VERSION}"
sudo apt-get install -y -q=2 "clang-${LLVM_VERSION}" "clang-tools-${LLVM_VERSION}"
- name: Run scan-build
run: .ci/scan-build.sh
# https://docs.docker.com/build/ci/github-actions/multi-platform/
docker-hub-build-and-publish:
needs: [detect-code-related-file-changes]
if: needs.detect-code-related-file-changes.outputs.has_code_related_changes == 'true'
timeout-minutes: 60
runs-on: ubuntu-24.04
steps:
- name: Check out the repo
uses: actions/checkout@v7
with:
submodules: 'true'
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@v4
if: github.event_name == 'push'
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
- name: Get short commit SHA1
if: github.event_name == 'push'
run: echo "short_hash=$(git rev-parse --short "$GITHUB_SHA")" >> "$GITHUB_ENV"
- name: Build and push
if: github.event_name == 'push'
uses: docker/build-push-action@v7
with:
push: true
context: .
platforms: linux/amd64,linux/arm64/v8
tags: sysprog21/rv32emu:latest, sysprog21/rv32emu:${{ env.short_hash }}
cache-from: type=gha
cache-to: type=gha,mode=max