Skip to content

ci: add Linux + MSYS2 matrix for rcore-tutorial smoke tests#46

Open
Lfan-ke wants to merge 19 commits intogevico:mainfrom
Lfan-ke:windows
Open

ci: add Linux + MSYS2 matrix for rcore-tutorial smoke tests#46
Lfan-ke wants to merge 19 commits intogevico:mainfrom
Lfan-ke:windows

Conversation

@Lfan-ke
Copy link
Copy Markdown
Collaborator

@Lfan-ke Lfan-ke commented Apr 11, 2026

Summary

This PR wires up Windows/MSYS2 as a first-class CI target alongside Linux for the rCore-Tutorial smoke tests (ch1–ch8), and fixes all build and runtime issues that prevented either platform from passing.

CI changes

  • Rename tg-rcore-tutorial.ymltg-rcore-tutorial-tests.yml so all test workflows share a consistent -tests suffix.
  • Add a fail-fast: false matrix with two entries:
    • linux (ubuntu-latest, bash): use rust-lld (default); no external GCC linker needed.
    • msys2 (windows-latest, msys2 {0}): install mingw-w64-x86_64-riscv64-unknown-elf-gcc via pacman; write ~/.cargo/config.toml via PowerShell to set check-revoke = false and -nostdlib rustflag; resolve the linker path dynamically with cygpath -w "$(which riscv64-unknown-elf-gcc)".
  • Guard the which/cygpath lookup with an if so the script degrades gracefully when the binary is not on PATH (local non-MSYS2 shells fall back to .cargo/config.toml).

JIT ABI fix (Windows x64)

All half-precision FPU helper functions in guest/riscv/src/riscv/fpu.rs that are called directly from JIT-generated x86-64 code were changed from extern "C" to extern "sysv64". On Windows, extern "C" uses the Microsoft x64 ABI (RCX/RDX/R8/R9 + shadow space) while the machina JIT backend always emits SysV AMD64 call sequences (RDI/RSI/RDX/RCX/R8/R9). Using the wrong ABI caused arguments to land in the wrong registers, leading to silent data corruption or crashes. extern "sysv64" is identical to extern "C" on Linux x86-64, so there is no Linux behaviour change.

Platform cfg guards

  • src/main.rs: keep #[cfg(unix)] on the LAST_TB_PC import — the only call site is crash_handler which uses POSIX signal APIs (sigaction, ucontext_t) unavailable on Windows. Add FirmwareCallFn (new -bios builtin type) unconditionally as it is defined without platform guards.

Merge from main

Includes all commits up to gevico/machina main (1c37cbb, -bios builtin mode with host-side SBI backend).

Test plan

  • cargo build passes on Windows (MSYS2 MINGW64)
  • cargo test --workspace passes on Windows (exit 0)
  • cargo fmt --check clean
  • rCore-Tutorial ch1–ch8 smoke test passes locally on MSYS2 (7/8; ch3 intermittent race — tracked separately)
  • CI: Linux matrix
  • CI: MSYS2 matrix

Closes #3
Closes #8

About #44

AsakuraMizu and others added 15 commits April 9, 2026 21:42
Fix all POSIX-specific API usages that prevented compilation on
Windows (x86_64-pc-windows-gnu / MSYS2 MinGW-w64). All changes
use #[cfg(unix)] / #[cfg(windows)] conditional compilation so
that both platforms receive equivalent functionality.

Changes:
- memory/src/ram.rs: replace libc::mmap/munmap with memmap2::MmapMut
- hw/virtio/src/block.rs: replace libc::mmap(MAP_SHARED) with memmap2::MmapMut
- accel/src/code_buffer.rs: platform-conditional RWX memory allocation
  (mmap on Unix, VirtualAlloc/VirtualProtect on Windows) and
  platform-conditional longjmp (siglongjmp vs machina_longjmp shim)
- accel/build.rs + accel/src/setjmp_shim.c: C shim exposing
  machina_setjmp/machina_longjmp on Windows to work around
  setjmp being a compiler intrinsic/macro in MinGW
- accel/src/exec/exec_loop.rs: platform-conditional SigJmpBuf size
  (200 bytes on Unix, 256 bytes on Windows) and sigsetjmp binding
- src/difftest.rs: same SigJmpBuf / sigsetjmp platform adaptation
- system/src/cpus.rs: use machina_longjmp on Windows instead of
  siglongjmp for TB abort in JIT helpers
- hw/core/src/chardev.rs: guard termios raw-mode and UnixStream
  SocketChardev with #[cfg(unix)]; restore_terminal() is always
  available but is a no-op on Windows
- src/main.rs: guard SIGSEGV crash handler with #[cfg(unix)];
  provide empty install_crash_handler() on Windows
- tests/src/tools/mod.rs: add #[cfg(windows)] child.kill() branch
- All affected Cargo.toml: make libc a [target.'cfg(unix)'.dependencies],
  add memmap2/windows-sys/cc where needed

Fixes: gevico#3
Fixes: gevico#8

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
add style check and format all files
Implements a new -bios builtin boot mode that starts the guest
kernel directly in S-mode without requiring external firmware
(no RustSBI/OpenSBI binary needed). The host provides SBI v2.0
services via a new SbiBackend type backed by sbi-spec constants.

Key changes:
- system/src/builtin.rs: new generic FirmwareCallFn framework
  for host-side firmware; documents the pattern for future ISAs
- system/src/cpus.rs: builtin_mode flag; handle_interrupt
  converts MTI to STIP so S-mode sees STI (mirrors M-mode FW)
- system/src/lib.rs: CpuManager gains set_firmware_handler() /
  cpu_mut(); S-mode ecalls are dispatched to the handler
- hw/riscv/src/sbi.rs: SBI v2.0 backend using sbi-spec crate
  for all EID/FID constants (legacy, base, time, srst, dbcn)
- hw/riscv/src/boot.rs: boot_builtin() sets up S-mode entry
  (pc, a0/a1, mideleg/medeleg/mie, PMP open)
- hw/char/src/uart.rs: read_rbr_nonblocking() for GETCHAR
- hw/intc/src/aclint.rs: set_mtimecmp() for SBI SET_TIMER
- src/main.rs: -bios builtin CLI arg; SBI wiring in machine cycle
- tests/src/hw_aclint.rs: re-anchor mtime before final mtimecmp
  write to eliminate wall-clock race on slow CI runners

Closes gevico#4

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
All functions called directly by JIT-generated code must use
System V AMD64 calling convention (RDI/RSI/RDX/RCX/R8/R9 for
args, RAX for return). On Windows, Rust's default extern "C"
uses the Microsoft x64 ABI (RCX/RDX/R8/R9 + shadow space),
causing wrong arguments to be read by the helpers.

Change all JIT-callable functions to extern "sysv64":
- accel/src/exec/exec_loop.rs: prologue_fn transmute target
- accel/src/translate.rs: prologue_fn transmute target
- guest/riscv/src/riscv/fpu.rs: all helper_f* FPU helpers
- guest/riscv/src/riscv/trans/helpers.rs: all helper_* helpers
- guest/riscv/src/riscv/trans/gen_zbc.rs: fn pointer type
- src/difftest.rs: prologue_fn transmute target
- system/src/cpus.rs: machina_mem_read/write, machina_csr_op

extern "sysv64" is valid on both Linux x86-64 (equivalent to
extern "C") and Windows x86-64 (overrides Microsoft x64 ABI),
so these changes preserve correct behavior on all platforms.

Fixes issues: gevico#3 and gevico#8

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
- smoke script: auto-detect machina binary (.exe on Windows, ELF on
  Linux) and set CARGO_TARGET_RISCV64GC_UNKNOWN_NONE_ELF_LINKER so
  riscv64 kernels build correctly from any bash environment (MSYS2,
  Git Bash, WSL2, native Linux)
- tests/tools: replace hardcoded /tmp paths with std::env::temp_dir()
  so irdump/irbackend tests work on Windows
- tests/frontend: gate difftest module behind #[cfg(target_os = linux)]
  since it requires riscv64-linux-gnu-gcc and qemu-riscv64
- tests/hw_chardev: guard SocketChardev import and test behind
  #[cfg(unix)] since the type only exists on Unix

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
- Add Windows/MSYS2 build support and cross-platform compatibility
- Fix Windows x64 JIT ABI: all helper functions use extern "sysv64"
- Fix cross-platform test and smoke script compatibility

Refs gevico#3 gevico#8

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
Rename tg-rcore-tutorial.yml to tg-rcore-tutorial-tests.yml so all
test workflows share a consistent -tests suffix.

Add a fail-fast: false matrix with two entries:
- linux (ubuntu-latest, bash): install gcc-riscv64-unknown-elf via
  apt so the smoke script can set the RISC-V linker on Linux.
- msys2 (windows-latest, msys2 {0}): set up MSYS2 MINGW64 with
  riscv64-unknown-elf-gcc, write ~/.cargo/config.toml via PowerShell
  to disable SSL revocation checks and pass -nostdlib to the GCC
  linker (required because rust-lld crashes on Windows for the
  riscv64gc-unknown-none-elf target).

Both entries add llvm-tools-preview to the Rust toolchain so
cargo-binutils works correctly.

Closes gevico#8
Closes gevico#3

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
hw/riscv: add -bios builtin mode with host-side SBI backend for gevico#4 In gevico/machina
The smoke script hardcoded C:/msys64/mingw64/bin/riscv64-unknown-elf-gcc.exe
as the linker path on non-Linux platforms. GitHub Actions runners may install
MSYS2 on a drive other than C: (observed: D:\a\_temp\msys64), causing all
chapter builds to fail with "linker not found".

Replace the hardcoded path with a dynamic lookup:

  cygpath -w "$(which riscv64-unknown-elf-gcc)"

This resolves the actual Windows-style path from whatever drive MSYS2 is
installed on, as long as the MINGW64 bin directory is in PATH (which
msys2/setup-msys2 guarantees when running in a msys2 {0} shell step).

Fixes gevico#8

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
Remove the Linux GCC linker override that caused all ch1-ch8 kernels
to fail with "cannot find crt0.o". On Linux, rust-lld (llvm-tools-preview)
is the correct default linker for riscv64gc-unknown-none-elf and needs
no override. Also remove the now-unnecessary apt-get install of
gcc-riscv64-unknown-elf from the CI workflow.

Closes gevico#3
Closes gevico#8

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
When riscv64-unknown-elf-gcc is not on PATH (e.g. the script is
invoked from a plain Git Bash session rather than MSYS2 MINGW64),
the previous unconditional `which` call would cause cygpath to
receive an empty string and exit non-zero, aborting the whole
script under set -euo pipefail.

Wrap the lookup in an `if` guard with stderr suppressed so that
when the binary is absent the override is silently skipped; cargo
then falls back to whatever linker is configured in .cargo/config.toml
(the os4ai workspace config or ~/.cargo/config.toml both supply the
correct path for their respective environments).

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
…h handler


Merge lfan-ke/main (af5421c: -bios builtin mode with host-side SBI
backend) into the windows branch.

Conflict resolutions:

guest/riscv/src/riscv/fpu.rs
  All half-precision FPU helper functions conflicted because main had
  extern "C" while windows requires extern "sysv64" for correct JIT
  ABI on Windows x64. Keep extern "sysv64" throughout; the sysv64
  calling convention is identical to extern "C" on Linux x86-64 so
  no Linux behaviour changes.

src/main.rs
  main added FirmwareCallFn (cross-platform) and inlined LAST_TB_PC
  into the cpus import without a cfg guard. Keep our #[cfg(unix)]
  guard on the LAST_TB_PC import because the only call site is
  crash_handler which is itself #[cfg(unix)] (uses POSIX signal APIs
  unavailable on Windows). Add FirmwareCallFn to the machina_system
  import unconditionally as it is defined without cfg guards and is
  needed by the new -bios builtin feature on all platforms.

Run cargo fmt to normalise formatting after the merge.

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
@Lfan-ke Lfan-ke force-pushed the windows branch 2 times, most recently from 92470ca to 1e8e23b Compare April 11, 2026 12:34
Lfan-ke added 4 commits April 11, 2026 20:38
# Conflicts:
#	guest/riscv/src/riscv/fpu.rs
Switch machina-tests.yml from dtolnay/rust-toolchain@stable to
actions-rust-lang/setup-rust-toolchain@v1, which has built-in retry
logic for transient network errors (e.g. "Connection reset by peer"
when downloading channel manifests from static.rust-lang.org).

Rename the tg-rcore-tutorial workflow display name from
rcore-tutorial-tests to rcore-tutorial-smoke-tests to match the
job naming convention used throughout the file.

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
Signed-off-by: Leo Cheng <chengkelfan@qq.com>
Remove unused MisaExt import from riscv_zba.rs.
Remove dead shadowed data/cursor bindings from test_recv_packet_ctrl_c
in gdbstub.rs.
Suppress unused_mut on child in sifive_test_reset_reboots: mut is
required for child.kill() on Windows but the Windows block is excluded
on Linux, causing the spurious warning.

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
Signed-off-by: Leo Cheng <chengkelfan@qq.com>
Increase per-chapter time budgets to give more headroom on slow CI
runners and debug builds:

  ch1-ch2: 30s  -> 60s
  ch3-ch4: 60s  -> 120s
  ch5:    180s  -> 240s
  ch6:    300s  -> 360s
  ch7-ch8: 600s -> 660s

Signed-off-by: Leo Cheng <chengkelfanke@gmail.com>
Signed-off-by: heke1228 <chengkelfan@qq.com>
Signed-off-by: Leo Cheng <chengkelfan@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows Platform Adaptation Summary for Machina RamBlock::new uses libc::mmap and fails to compile on Windows

3 participants