diff --git a/.github/workflows/test_nixos_full.yml b/.github/workflows/test_nixos_full.yml index 97b485bd6..d18141078 100644 --- a/.github/workflows/test_nixos_full.yml +++ b/.github/workflows/test_nixos_full.yml @@ -39,7 +39,7 @@ jobs: - name: Test nix commands run: | make nixos NIXOS_DISK_SIZE_IN_MB=6144 NIXOS_TEST_COMMAND='test-nix-commands' - make run_nixos || true + make run_nixos - name: Check results run: | @@ -71,7 +71,7 @@ jobs: - name: Run podman commands run: | make nixos NIXOS_DISK_SIZE_IN_MB=8192 NIXOS_TEST_COMMAND='test-podman' - make run_nixos || true + make run_nixos - name: Check results run: | diff --git a/.github/workflows/test_nixos_minimal.yml b/.github/workflows/test_nixos_minimal.yml index a0fdc2785..c852ded16 100644 --- a/.github/workflows/test_nixos_minimal.yml +++ b/.github/workflows/test_nixos_minimal.yml @@ -38,8 +38,8 @@ jobs: image: asterinas/asterinas:0.17.0-20251228 options: --privileged -v /dev:/dev -v ${{ github.workspace }}:/root/asterinas run: | - make nixos NIXOS_DISK_SIZE_IN_MB=6144 NIXOS_TEST_COMMAND='hello-asterinas' || true - make run_nixos || true + make nixos NIXOS_DISK_SIZE_IN_MB=6144 NIXOS_TEST_COMMAND='hello-asterinas' + make run_nixos - name: Check results run: | tail --lines 10 ${{ github.workspace }}/qemu.log | grep -q "^Hello Asterinas!" || (echo "Test NixOS failed" && exit 1) diff --git a/Makefile b/Makefile index 5aa0f92e6..d1cf8c06f 100644 --- a/Makefile +++ b/Makefile @@ -331,7 +331,7 @@ iso: # Build the Asterinas NixOS ISO installer image and then do installation run_iso: OVMF = off run_iso: - @./tools/nixos/run_iso.sh + @./tools/nixos/run.sh iso # Create an Asterinas NixOS installation on host nixos: BOOT_PROTOCOL = linux-efi-handover64 @@ -343,7 +343,7 @@ nixos: # run the NixOS run_nixos: OVMF = off run_nixos: - @./tools/nixos/run_nixos.sh target/nixos + @./tools/nixos/run.sh nixos # Build the Asterinas NixOS patched packages cachix: diff --git a/osdk/src/bundle/mod.rs b/osdk/src/bundle/mod.rs index 78aa00015..6c9ff42a6 100644 --- a/osdk/src/bundle/mod.rs +++ b/osdk/src/bundle/mod.rs @@ -296,9 +296,14 @@ impl Bundle { let qemu_exit_code = exit_status.code().unwrap(); let kernel_exit_code = qemu_exit_code >> 1; match kernel_exit_code { - 0x10 /*ostd::QemuExitCode::Success*/ => { std::process::exit(0); }, - 0x20 /*ostd::QemuExitCode::Failed*/ => { std::process::exit(1); }, - _ /* unknown, e.g., a triple fault */ => { std::process::exit(2) }, + // Success exit through ACPI. + 0x0 => std::process::exit(0), + // Corresponds to `ostd::QemuExitCode::Success`. + 0x10 => std::process::exit(0), + // Corresponds to `ostd::QemuExitCode::Failed`. + 0x20 => std::process::exit(1), + // Unknown exit code, e.g., a triple fault. + _ => std::process::exit(2), } } diff --git a/tools/nixos/run.sh b/tools/nixos/run.sh new file mode 100755 index 000000000..1e8fd8bca --- /dev/null +++ b/tools/nixos/run.sh @@ -0,0 +1,93 @@ +#!/bin/sh + +# SPDX-License-Identifier: MPL-2.0 + +# Run a NixOS installation or NixOS ISO installer image built by the root Makefile inside a VM +# +# Usage: ./run.sh [nixos | iso] + +set -e + +usage() { + echo "Usage: $0 [nixos | iso]" + exit 1 +} + +if [ "$#" -ne 1 ]; then + usage +fi + +MODE=$1 +SCRIPT_DIR=$(dirname "$0") +ASTERINAS_DIR=$(realpath "${SCRIPT_DIR}/../..") + +# Base QEMU arguments +BASE_QEMU_ARGS="qemu-system-x86_64 \ + -bios /root/ovmf/release/OVMF.fd \ +" + +# Mode-specific QEMU arguments +case "$MODE" in + nixos) + NIXOS_DIR="${ASTERINAS_DIR}/target/nixos" + QEMU_ARGS="${BASE_QEMU_ARGS} \ + -drive if=none,format=raw,id=u0,file=${NIXOS_DIR}/asterinas.img \ + -device virtio-blk-pci,drive=u0,disable-legacy=on,disable-modern=off \ + " + ;; + iso) + ASTER_IMAGE_PATH=${ASTERINAS_DIR}/target/nixos/asterinas.img + NIXOS_DISK_SIZE_IN_MB=${NIXOS_DISK_SIZE_IN_MB:-8192} + ISO_IMAGE_PATH=$(find "${ASTERINAS_DIR}/target/nixos/iso_image/iso" -name "*.iso" | head -n 1) + + if [ ! -f "$ISO_IMAGE_PATH" ]; then + echo "Error: ISO_IMAGE not found!" + exit 1 + fi + + rm -f "${ASTER_IMAGE_PATH}" + echo "Creating image at ${ASTER_IMAGE_PATH} of size ${NIXOS_DISK_SIZE_IN_MB}MB......" + dd if=/dev/zero of="${ASTER_IMAGE_PATH}" bs=1M count=${NIXOS_DISK_SIZE_IN_MB} status=none + echo "Image created successfully!" + + QEMU_ARGS="${BASE_QEMU_ARGS} \ + -cdrom ${ISO_IMAGE_PATH} -boot d \ + -drive if=none,format=raw,id=u0,file=${ASTER_IMAGE_PATH} \ + -device virtio-blk-pci,drive=u0,disable-legacy=on,disable-modern=off \ + " + ;; + *) + usage + ;; +esac + +if [ "${ENABLE_KVM}" = "1" ]; then + QEMU_ARGS="${QEMU_ARGS} -accel kvm" +fi + +COMMON_QEMU_ARGS=$(${ASTERINAS_DIR}/tools/qemu_args.sh common 2>/dev/null) +QEMU_ARGS=" + ${QEMU_ARGS} \ + ${COMMON_QEMU_ARGS} \ +" + +# The kernel uses a specific value to signal a successful shutdown via the +# isa-debug-exit device. +KERNEL_SUCCESS_EXIT_CODE=16 # 0x10 in hexadecimal +# QEMU translates the value written to the isa-debug-exit device into a final +# process exit code using following formula. +QEMU_SUCCESS_EXIT_CODE=$(((KERNEL_SUCCESS_EXIT_CODE << 1) | 1)) + +# Execute QEMU +# shellcheck disable=SC2086 +${QEMU_ARGS} || exit_code=$? +exit_code=${exit_code:-0} + +# Check if the execution was successful: +# - Exit code 0: Normal successful exit (e.g., ACPI shutdown or clean termination) +# - Exit code $QEMU_SUCCESS_EXIT_CODE: Kernel signaled success via isa-debug-exit device +if [ ${exit_code} -eq 0 ] || [ ${exit_code} -eq ${QEMU_SUCCESS_EXIT_CODE} ]; then + exit 0 +fi + +exit ${exit_code} \ No newline at end of file diff --git a/tools/nixos/run_iso.sh b/tools/nixos/run_iso.sh deleted file mode 100755 index ca0c47835..000000000 --- a/tools/nixos/run_iso.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash - -# SPDX-License-Identifier: MPL-2.0 - -set -e - -SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) -ASTERINAS_DIR=$(realpath ${SCRIPT_DIR}/../..) -ASTER_IMAGE_PATH=${ASTERINAS_DIR}/target/nixos/asterinas.img -NIXOS_DISK_SIZE_IN_MB=${NIXOS_DISK_SIZE_IN_MB:-8192} -ISO_IMAGE_PATH=$(realpath ${ASTERINAS_DIR}/target/nixos/iso_image/iso/*.iso) - -if [ ! -f "$ISO_IMAGE_PATH" ]; then - echo "Error: ISO_IMAGE not found!" - exit 1 -fi - -rm -f ${ASTER_IMAGE_PATH} -echo "Creating image at ${ASTER_IMAGE_PATH} of size ${NIXOS_DISK_SIZE_IN_MB}MB......" -dd if=/dev/zero of=${ASTER_IMAGE_PATH} bs=1M count=${NIXOS_DISK_SIZE_IN_MB} -echo "Image created successfully!" - -QEMU_ARGS="qemu-system-x86_64 \ - -bios /root/ovmf/release/OVMF.fd \ - -cdrom ${ISO_IMAGE_PATH} -boot d \ - -drive if=none,format=raw,id=u0,file=${ASTER_IMAGE_PATH} \ - -device virtio-blk-pci,drive=u0,disable-legacy=on,disable-modern=off \ -" - -if [ "${ENABLE_KVM}" = "1" ]; then - QEMU_ARGS="${QEMU_ARGS} -accel kvm" -fi - -COMMON_QEMU_ARGS=$(${SCRIPT_DIR}/../qemu_args.sh common 2>/dev/null) -QEMU_ARGS=" - ${QEMU_ARGS} \ - ${COMMON_QEMU_ARGS} \ -" - -${QEMU_ARGS} diff --git a/tools/nixos/run_nixos.sh b/tools/nixos/run_nixos.sh deleted file mode 100755 index f6cbdbecb..000000000 --- a/tools/nixos/run_nixos.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -# SPDX-License-Identifier: MPL-2.0 - -set -e - -NIXOS_DIR=$(realpath $1) -QEMU_ARGS="qemu-system-x86_64 \ - -bios /root/ovmf/release/OVMF.fd \ - -drive if=none,format=raw,id=u0,file=${NIXOS_DIR}/asterinas.img \ - -device virtio-blk-pci,drive=u0,disable-legacy=on,disable-modern=off \ -" - -if [ "${ENABLE_KVM}" = "1" ]; then - QEMU_ARGS="${QEMU_ARGS} -accel kvm" -fi - -COMMON_QEMU_ARGS=$(${NIXOS_DIR}/../../tools/qemu_args.sh common 2>/dev/null) -QEMU_ARGS=" - ${QEMU_ARGS} \ - ${COMMON_QEMU_ARGS} \ -" - -${QEMU_ARGS}