rv64.sh (6065B)
1 #!/usr/bin/env bash 2 # test/smoke/rv64.sh — end-to-end smoke test for the rv64 podman/qemu path, on 3 # the shared Type-K mode-P kit (test/lib/kit_sh_kit.sh). 4 # 5 # Phase-2 of the multi-arch bring-up: prove the test/lib/exec_target.sh helper 6 # can build, queue, and run a riscv64-linux ELF before any kit-emitted rv64 7 # bytes exist. Builds a tiny freestanding static executable with 8 # clang --target=riscv64-linux-gnu and pushes it through 9 # exec_target_run / exec_target_queue+flush, asserting exit code 42 on both 10 # paths. This is one inline program, so it is a single-scenario procedural 11 # suite (build, exec, assert rc) rather than a file-glob corpus. 12 # 13 # Skipped if clang lacks the riscv64-linux-gnu target, ld.lld is missing, or no 14 # runner (podman or qemu-riscv64) is available. Skip is treated as failure 15 # unless KIT_TEST_ALLOW_SKIP=1 (the shared kit_exit honors it). 16 17 set -u 18 19 ROOT="$(cd "$(dirname "$0")/../.." && pwd)" 20 BUILD_DIR="$ROOT/build/test/smoke-rv64" 21 mkdir -p "$BUILD_DIR" 22 23 KIT_KIT_DIR="$ROOT/test/lib" 24 # shellcheck source=../lib/kit_sh_kit.sh 25 . "$ROOT/test/lib/kit_sh_kit.sh" 26 kit_report_init 27 28 # This harness's convention (preserved from the original smoke runner): a SKIP 29 # is a failure unless KIT_TEST_ALLOW_SKIP=1, so CI catches a degraded run. 30 KIT_SKIP_IS_FAILURE=1 31 32 # Mode-P suites are SERIAL and share one $work sandbox. 33 work="$BUILD_DIR" 34 35 # ---- detect prerequisites -------------------------------------------------- 36 # 37 # Delegated to test/lib/check_rv64_env.sh (the kit-rv64 doctor). It 38 # probes clang/lld/qemu/podman/native, prints a per-tool ok/MISSING 39 # line with install hints, and populates RV64_* globals plus a single 40 # READY/BLOCKED summary. The smoke script reuses those globals below 41 # and never re-implements the detection. 42 # shellcheck source=../lib/check_rv64_env.sh 43 . "$(cd "$(dirname "$0")/.." && pwd)/lib/check_rv64_env.sh" 44 check_rv64_env 45 46 have_clang_rv64="$RV64_HAVE_CLANG_TARGET" 47 have_lld="$RV64_HAVE_LLD" 48 49 CLANG_TARGET="--target=riscv64-linux-gnu" 50 51 # Variables expected by exec_target.sh. The aarch64 helper expects 52 # these names regardless of target arch — they describe the host 53 # detection rather than the target. For rv64-only smoke we don't need 54 # QEMU_BIN (that's the aarch64 user-mode qemu); rv64 picks up 55 # qemu-riscv64 automatically inside _exec_target_qemu (which honors 56 # QEMU_RV64_BIN from the doctor as well). 57 have_qemu=0 58 QEMU_BIN="" 59 have_podman="$RV64_HAVE_PODMAN" 60 QEMU_RV64_BIN="$RV64_QEMU_BIN" 61 arch_raw="$(uname -m 2>/dev/null || true)" 62 is_aarch64=0 63 { [ "$arch_raw" = "aarch64" ] || [ "$arch_raw" = "arm64" ]; } && is_aarch64=1 64 export have_qemu QEMU_BIN have_podman is_aarch64 QEMU_RV64_BIN 65 66 EXEC_TARGET_MOUNT_ROOT="$BUILD_DIR" 67 export EXEC_TARGET_MOUNT_ROOT 68 # shellcheck source=../lib/exec_target.sh 69 . "$ROOT/test/lib/exec_target.sh" 70 71 if [ "$have_clang_rv64" -eq 0 ]; then 72 skip_test "build" "clang --target=riscv64-linux-gnu unavailable — install: $(_rv64_hint_clang)" 73 kit_summary test-smoke-rv64; kit_exit 74 fi 75 if [ "$have_lld" -eq 0 ]; then 76 skip_test "build" "ld.lld unavailable — install: $(_rv64_hint_lld)" 77 kit_summary test-smoke-rv64; kit_exit 78 fi 79 if ! exec_target_supported rv64; then 80 # No runner: pick the most actionable hint. qemu is the lightest 81 # to install on a contributor box; podman is the second-best. 82 skip_test "exec" "no rv64 runner — easiest fix: $(_rv64_hint_qemu); or set up podman ($(_rv64_hint_podman_riscv64))" 83 kit_summary test-smoke-rv64; kit_exit 84 fi 85 86 # ---- build a tiny freestanding riscv64 ELF ---------------------------------- 87 88 # Direct syscall in _start: SYS_exit_group on rv64 is 94 (a7), exit 89 # code 42 (a0). No libc, no relocations, no PIE. The point is to 90 # exercise the harness pipeline (clang cross-compile -> podman/qemu 91 # run -> recorded rc), not to build a complete program. 92 SRC="$BUILD_DIR/smoke.c" 93 cat >"$SRC" <<'EOF' 94 __attribute__((noreturn)) void _start(void) { 95 register long a7 __asm__("a7") = 94; /* sys_exit_group */ 96 register long a0 __asm__("a0") = 42; 97 __asm__ volatile("ecall" : : "r"(a7), "r"(a0) : "memory"); 98 __builtin_unreachable(); 99 } 100 EOF 101 102 EXE="$BUILD_DIR/smoke.exe" 103 if ! clang $CLANG_TARGET -march=rv64gc -fuse-ld=lld \ 104 -O1 -ffreestanding -fno-stack-protector \ 105 -fno-PIC -fno-pie -nostdlib -static \ 106 -Wl,-e,_start \ 107 "$SRC" -o "$EXE" 2>"$BUILD_DIR/build.err"; then 108 not_ok "build" "$BUILD_DIR/build.err" 109 kit_summary test-smoke-rv64; kit_exit 110 fi 111 ok "build" 112 113 # Classify the recorded rc on a non-42 result. 125/126/127 are podman/shell 114 # "couldn't execute" rcs — treat those as setup failures and run the podman 115 # classifier so the contributor sees one line saying *which* podman issue it 116 # is. ERRFILE / NAME / RC are passed in. 117 note_run_fail() { 118 local name="$1" rc="$2" errfile="$3" diag="$BUILD_DIR/$4.diag" 119 if [ "${RV64_HAVE_PODMAN:-0}" -eq 1 ] && \ 120 { [ "$rc" -eq 125 ] || [ "$rc" -eq 126 ] || [ "$rc" -eq 127 ]; }; then 121 printf '(rc=%s) — %s\n' "$rc" "$(classify_podman_rv64_error "$errfile")" > "$diag" 122 else 123 printf 'expected 42 got %s; see %s\n' "$rc" "$errfile" > "$diag" 124 fi 125 not_ok "$name" "$diag" 126 } 127 128 # ---- exec_target_run --------------------------------------------------------- 129 130 exec_target_run rv64 "$EXE" "$BUILD_DIR/run.out" "$BUILD_DIR/run.err" 131 if [ "$RUN_RC" -eq 42 ]; then 132 ok "exec_target_run rv64 (rc=42)" 133 else 134 note_run_fail "exec_target_run rv64" "$RUN_RC" "$BUILD_DIR/run.err" "run" 135 fi 136 137 # ---- exec_target_queue + flush ---------------------------------------------- 138 139 exec_target_queue rv64 smoke "$EXE" \ 140 "$BUILD_DIR/q.out" "$BUILD_DIR/q.err" "$BUILD_DIR/q.rc" 141 exec_target_flush 142 if [ ! -f "$BUILD_DIR/q.rc" ]; then 143 echo "no rc file produced" > "$BUILD_DIR/q.diag" 144 not_ok "exec_target_queue+flush rv64" "$BUILD_DIR/q.diag" 145 else 146 Q_RC="$(cat "$BUILD_DIR/q.rc")" 147 if [ "$Q_RC" -eq 42 ]; then 148 ok "exec_target_queue+flush rv64 (rc=42)" 149 else 150 note_run_fail "exec_target_queue+flush rv64" "$Q_RC" "$BUILD_DIR/q.err" "q" 151 fi 152 fi 153 154 kit_summary test-smoke-rv64 155 kit_exit