Migrate virtio-net from semu #4542
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |