From 4a1976dd0c388f4a3df2a6fc55f9344c0247d95e Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Thu, 20 Feb 2025 22:41:54 +0800 Subject: [PATCH 1/4] Enable VirtIO block to access hostOS /dev/ block devices The user may not always have a disk image but might have a /dev/x block device, such as a USB drive that they want to share with the guest OS. So, allowing this type of virtio-blk source is intuitive. To support this, ioctl is used to retrieve the actual size of the /dev/x block device. This implementation supports both Apple and Linux platforms. On Apple platforms, mmap() on block devices appears to be unsupported with various flag combinations. To address this, a fallback mechanism is added and used when mmap() fails, using malloc() along with pread(), pwrite() and fsync() on the block device fd to emulate the behavior of mmap(). Additionally, the initial fallback was incomplete, as it only allocated heap memory without loading the block device's content into memory. This commit resolves the issue by properly reading the device contents into the allocated buffer. Since there may be asynchronous exits, a new rv_fsync_device() function is introduced to ensure the block device is properly synchronized during such exits. To fully support this fallback, disk_fd and disk_size are now stored in the vblk state during its initialization. Close #544 --- src/devices/virtio-blk.c | 129 +++++++++++++++++++++++++++++++++------ src/devices/virtio.h | 2 + src/main.c | 5 ++ src/riscv.c | 44 ++++++++++++- 4 files changed, 161 insertions(+), 19 deletions(-) diff --git a/src/devices/virtio-blk.c b/src/devices/virtio-blk.c index a93f0427..5f4506ff 100644 --- a/src/devices/virtio-blk.c +++ b/src/devices/virtio-blk.c @@ -4,15 +4,30 @@ */ #include +#include #include +#include #include #include #include #include +#include #include #include #include +/* + * The /dev/ block devices cannot be embedded to the part of the wasm. + * Thus, accessing /dev/ block devices is not supported for wasm. + */ +#if !defined(__EMSCRIPTEN__) +#if defined(__APPLE__) +#include /* DKIOCGETBLOCKCOUNT and DKIOCGETBLOCKSIZE */ +#else +#include /* BLKGETSIZE64 */ +#endif +#endif /* !defined(__EMSCRIPTEN__) */ + #include "virtio.h" #define DISK_BLK_SIZE 512 @@ -97,12 +112,16 @@ static void virtio_blk_update_status(virtio_blk_state_t *vblk, uint32_t status) uint32_t device_features = vblk->device_features; uint32_t *ram = vblk->ram; uint32_t *disk = vblk->disk; + uint64_t disk_size = vblk->disk_size; + int disk_fd = vblk->disk_fd; void *priv = vblk->priv; uint32_t capacity = VBLK_PRIV(vblk)->capacity; memset(vblk, 0, sizeof(*vblk)); vblk->device_features = device_features; vblk->ram = ram; vblk->disk = disk; + vblk->disk_size = disk_size; + vblk->disk_fd = disk_fd; vblk->priv = priv; VBLK_PRIV(vblk)->capacity = capacity; } @@ -388,6 +407,12 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, exit(EXIT_FAILURE); } + /* + * For mmap_fallback, if vblk is not specified, disk_fd should remain -1 and + * no fsync should be performed on exit. + */ + vblk->disk_fd = -1; + /* Allocate memory for the private member */ vblk->priv = &vblk_configs[vblk_dev_cnt++]; @@ -402,14 +427,54 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, /* Open disk file */ int disk_fd = open(disk_file, readonly ? O_RDONLY : O_RDWR); if (disk_fd < 0) { - rv_log_error("Could not open %s", disk_file); - exit(EXIT_FAILURE); + rv_log_error("Could not open %s: %s", disk_file, strerror(errno)); + goto fail; } - /* Get the disk image size */ struct stat st; - fstat(disk_fd, &st); - VBLK_PRIV(vblk)->disk_size = st.st_size; + if (fstat(disk_fd, &st) == -1) { + rv_log_error("fstat failed: %s", strerror(errno)); + goto disk_size_fail; + } + + const char *disk_file_dirname = dirname(disk_file); + if (!disk_file_dirname) { + rv_log_error("Fail dirname disk_file: %s: %s", disk_file, + strerror(errno)); + goto disk_size_fail; + } + /* Get the disk size */ + uint64_t disk_size; + if (!strcmp(disk_file_dirname, "/dev")) { /* from /dev/, leverage ioctl */ +#if !defined(__EMSCRIPTEN__) +#if defined(__APPLE__) + uint32_t block_size; + uint64_t block_count; + if (ioctl(disk_fd, DKIOCGETBLOCKCOUNT, &block_count) == -1) { + rv_log_error("DKIOCGETBLOCKCOUNT failed: %s", strerror(errno)); + goto disk_size_fail; + } + if (ioctl(disk_fd, DKIOCGETBLOCKSIZE, &block_size) == -1) { + rv_log_error("DKIOCGETBLOCKSIZE failed: %s", strerror(errno)); + goto disk_size_fail; + } + disk_size = block_count * block_size; +#else /* Linux */ + if (ioctl(disk_fd, BLKGETSIZE64, &disk_size) == -1) { + rv_log_error("BLKGETSIZE64 failed: %s", strerror(errno)); + goto disk_size_fail; + } +#endif +#endif /* !defined(__EMSCRIPTEN__) */ + } else { /* other path, stat it as normal file */ + struct stat st; + if (fstat(disk_fd, &st) == -1) { + rv_log_error("fstat failed"); + goto disk_size_fail; + } + disk_size = st.st_size; + } + VBLK_PRIV(vblk)->disk_size = disk_size; /* Set up the disk memory */ uint32_t *disk_mem; @@ -417,15 +482,38 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, disk_mem = mmap(NULL, VBLK_PRIV(vblk)->disk_size, readonly ? PROT_READ : (PROT_READ | PROT_WRITE), MAP_SHARED, disk_fd, 0); - if (disk_mem == MAP_FAILED) - goto err; -#else + if (disk_mem == MAP_FAILED) { + if (errno != EINVAL) + goto disk_mem_err; + /* + * On Apple platforms, mmap() on block devices appears to be unsupported + * and EINVAL is set to errno. + */ + rv_log_trace( + "Fallback to malloc-based block device due to mmap() failure"); + goto mmap_fallback; + } + /* + * disk_fd should be closed on exit after flushing heap data back to the + * device when using mmap_fallback. + */ + close(disk_fd); + goto disk_mem_ok; +#endif + +mmap_fallback: disk_mem = malloc(VBLK_PRIV(vblk)->disk_size); if (!disk_mem) - goto err; -#endif + goto disk_mem_err; + vblk->disk_fd = disk_fd; + vblk->disk_size = disk_size; + if (pread(disk_fd, disk_mem, disk_size, 0) == -1) { + rv_log_error("pread block device failed: %s", strerror(errno)); + goto disk_mem_err; + } + +disk_mem_ok: assert(!(((uintptr_t) disk_mem) & 0b11)); - close(disk_fd); vblk->disk = disk_mem; VBLK_PRIV(vblk)->capacity = @@ -436,9 +524,14 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, return disk_mem; -err: - rv_log_error("Could not map disk %s", disk_file); - return NULL; +disk_mem_err: + rv_log_error("Could not map disk %s: %s", disk_file, strerror(errno)); + +disk_size_fail: + close(disk_fd); + +fail: + exit(EXIT_FAILURE); } virtio_blk_state_t *vblk_new() @@ -450,10 +543,12 @@ virtio_blk_state_t *vblk_new() void vblk_delete(virtio_blk_state_t *vblk) { + /* mmap_fallback is used */ + if (vblk->disk_fd != -1) + free(vblk->disk); #if HAVE_MMAP - munmap(vblk->disk, VBLK_PRIV(vblk)->disk_size); -#else - free(vblk->disk); + else + munmap(vblk->disk, VBLK_PRIV(vblk)->disk_size); #endif free(vblk); } diff --git a/src/devices/virtio.h b/src/devices/virtio.h index b0cbadd3..28da79f7 100644 --- a/src/devices/virtio.h +++ b/src/devices/virtio.h @@ -103,6 +103,8 @@ typedef struct { /* supplied by environment */ uint32_t *ram; uint32_t *disk; + uint64_t disk_size; + int disk_fd; /* implementation-specific */ void *priv; } virtio_blk_state_t; diff --git a/src/main.c b/src/main.c index bed7bc7a..8e366519 100644 --- a/src/main.c +++ b/src/main.c @@ -298,6 +298,11 @@ int main(int argc, char **args) /* finalize the RISC-V runtime */ rv_delete(rv); + /* + * Other translation units cannot update the pointer, update it here + * to prevent multiple atexit()'s callback be called. + */ + rv = NULL; rv_log_info("RISC-V emulator is destroyed"); end: diff --git a/src/riscv.c b/src/riscv.c index a5f344ec..36cabefb 100644 --- a/src/riscv.c +++ b/src/riscv.c @@ -390,7 +390,43 @@ static void rv_async_block_clear() return; #endif /* !RV32_HAS(JIT) */ } -#endif + +static void rv_fsync_device() +{ + if (!rv) + return; + + vm_attr_t *attr = PRIV(rv); + /* + * mmap_fallback, may need to write and sync the device + * + * vblk is optional, so it could be NULL + */ + if (attr->vblk) { + if (attr->vblk->disk_fd >= 3) { + if (attr->vblk->device_features & VIRTIO_BLK_F_RO) /* readonly */ + goto end; + + if (pwrite(attr->vblk->disk_fd, attr->vblk->disk, + attr->vblk->disk_size, 0) == -1) { + rv_log_error("pwrite block device failed: %s", strerror(errno)); + return; + } + + if (fsync(attr->vblk->disk_fd) == -1) { + rv_log_error("fsync block device failed: %s", strerror(errno)); + return; + } + rv_log_info("Sync block device OK"); + + end: + close(attr->vblk->disk_fd); + } + + vblk_delete(attr->vblk); + } +} +#endif /* RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER) */ riscv_t *rv_create(riscv_user_t rv_attr) { @@ -402,6 +438,8 @@ riscv_t *rv_create(riscv_user_t rv_attr) #if RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER) /* register cleaning callback for CTRL+a+x exit */ atexit(rv_async_block_clear); + /* register device sync callback for CTRL+a+x exit */ + atexit(rv_fsync_device); #endif /* copy over the attr */ @@ -549,6 +587,7 @@ riscv_t *rv_create(riscv_user_t rv_attr) attr->uart->out_fd = attr->fd_stdout; /* setup virtio-blk */ + attr->vblk = NULL; if (attr->data.system.vblk_device) { /* Currently, only used for block image path and permission */ #define MAX_OPTS 2 @@ -719,7 +758,8 @@ void rv_delete(riscv_t *rv) #if RV32_HAS(SYSTEM) && !RV32_HAS(ELF_LOADER) u8250_delete(attr->uart); plic_delete(attr->plic); - vblk_delete(attr->vblk); + /* sync device, cleanup inside the callee */ + rv_fsync_device(); #endif free(rv); } From 15061297bba2892ee255d6d0ef1fd847a3fd821c Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Tue, 18 Mar 2025 04:31:20 +0800 Subject: [PATCH 2/4] Filter out non block devices from /dev/ --- src/devices/virtio-blk.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/devices/virtio-blk.c b/src/devices/virtio-blk.c index 5f4506ff..5ee34085 100644 --- a/src/devices/virtio-blk.c +++ b/src/devices/virtio-blk.c @@ -446,6 +446,10 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, /* Get the disk size */ uint64_t disk_size; if (!strcmp(disk_file_dirname, "/dev")) { /* from /dev/, leverage ioctl */ + if ((st.st_mode & S_IFMT) != S_IFBLK) { + rv_log_error("%s is not block device", disk_file); + goto fail; + } #if !defined(__EMSCRIPTEN__) #if defined(__APPLE__) uint32_t block_size; @@ -466,12 +470,7 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, } #endif #endif /* !defined(__EMSCRIPTEN__) */ - } else { /* other path, stat it as normal file */ - struct stat st; - if (fstat(disk_fd, &st) == -1) { - rv_log_error("fstat failed"); - goto disk_size_fail; - } + } else { /* other path, get the size of block device via stat buffer */ disk_size = st.st_size; } VBLK_PRIV(vblk)->disk_size = disk_size; From 43031388a89c764a4898ed63d9bcb2c3712ce0c3 Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Tue, 18 Mar 2025 13:51:32 +0800 Subject: [PATCH 3/4] Update README for sharing hostOS /dev/ block devices with guestOS --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 092a5757..dd218d54 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,8 @@ Generate ext4 image file for virtio block device in Unix-like system: $ dd if=/dev/zero of=disk.img bs=4M count=32 $ mkfs.ext4 disk.img ``` +Instead of creating a new block device image, you can share the hostOS's existing block devices. For example, on macOS host, specify the block device path as `-x vblk:/dev/disk3`, or on Linux host as `-x vblk:/dev/loop3`, assuming these paths point to valid block devices. + Mount the virtual block device and create a test file after booting, note that root privilege is required to mount and unmount a disk: ```shell # mkdir mnt From e2e87ee26385a3602bdbee4629d58bc85e986fa1 Mon Sep 17 00:00:00 2001 From: ChinYikMing Date: Thu, 20 Mar 2025 02:15:55 +0800 Subject: [PATCH 4/4] CI: Refine Linux boot script for new feature verification The Linux boot script previously tested both booting and VirtIO block access simultaneously. This commit refines the boot script to test each guest Linux feature independently. In addition, a new color (yellow) is introduced to clearly indicate which test is currently running in the CI, improving debugging capabilities. For future VirtIO device tests or other new features, TEST_OPTIONS and EXPECT_CMDS can be easily updated to extend the tests, enhancing the overall flexibility of the script. The VirtIO block device image or loop device is prepared by the .ci/boot-linux-prepare.sh script which decouples data and control for system emulation validation in .ci/boot-linux.sh. This script can be extended in the future to support additional VirtIO devices by preparing their associated data prior to Linux boot validation. The system validation flow is abstracted into a variable called BOOT_LINUX_TEST which uses sudo only for data preparation and does not use sudo to run .ci/boot-linux.sh, enhancing security when launching the system VM. --- .ci/boot-linux-prepare.sh | 67 ++++++++++++++++++++++ .ci/boot-linux.sh | 111 ++++++++++++++++++++++++------------- .github/workflows/main.yml | 26 +++++++-- 3 files changed, 158 insertions(+), 46 deletions(-) create mode 100755 .ci/boot-linux-prepare.sh diff --git a/.ci/boot-linux-prepare.sh b/.ci/boot-linux-prepare.sh new file mode 100755 index 00000000..c7210897 --- /dev/null +++ b/.ci/boot-linux-prepare.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +. .ci/common.sh + +check_platform + +VBLK_IMG=build/disk.img +which dd >/dev/null 2>&1 || { echo "Error: dd not found"; exit 1; } +which mkfs.ext4 >/dev/null 2>&1 || which $(brew --prefix e2fsprogs)/sbin/mkfs.ext4 >/dev/null 2>&1 || \ + { echo "Error: mkfs.ext4 not found"; exit 1; } +which 7z >/dev/null 2>&1 || { echo "Error: 7z not found"; exit 1; } + +ACTION=$1 + +case "$ACTION" in + setup) + # Setup a disk image + dd if=/dev/zero of=${VBLK_IMG} bs=4M count=32 + + # Setup a /dev/ block device with ${VBLK_IMG} to test guestOS access to hostOS /dev/ block device + case "${OS_TYPE}" in + Linux) + mkfs.ext4 ${VBLK_IMG} + BLK_DEV=$(losetup -f) + losetup ${BLK_DEV} ${VBLK_IMG} + ;; + Darwin) + $(brew --prefix e2fsprogs)/sbin/mkfs.ext4 ${VBLK_IMG} + BLK_DEV=$(hdiutil attach -nomount ${VBLK_IMG}) + ;; + esac + + # On Linux, ${VBLK_IMG} will be created by root and owned by root:root. + # Even if "others" have read and write (rw) permissions, accessing the file for certain operations may + # still require elevated privileges (e.g., setuid). + # To simplify this, we change the ownership to a non-root user. + # Use this with caution—changing ownership to runner:runner is specific to the GitHub CI environment. + chown runner: ${VBLK_IMG} + # Add other's rw permission to the disk image and device, so non-superuser can rw them + chmod o+r,o+w ${VBLK_IMG} + chmod o+r,o+w ${BLK_DEV} + + # Export ${BLK_DEV} to a tmp file. Then, source to "$GITHUB_ENV" in job step. + echo "export BLK_DEV=${BLK_DEV}" > "${TMP_FILE}" + ;; + cleanup) + # Detach the /dev/loopx(Linux) or /dev/diskx(Darwin) + case "${OS_TYPE}" in + Linux) + losetup -d ${BLK_DEV} + ;; + Darwin) + hdiutil detach ${BLK_DEV} + ;; + esac + + # delete disk image + rm -f ${VBLK_IMG} + + # delete tmp file + rm "${TMP_FILE}" + ;; + *) + printf "Usage: %s {setup|cleanup}\n" "$0" + exit 1 + ;; +esac diff --git a/.ci/boot-linux.sh b/.ci/boot-linux.sh index f439fadb..21feaefb 100755 --- a/.ci/boot-linux.sh +++ b/.ci/boot-linux.sh @@ -1,5 +1,9 @@ #!/usr/bin/env bash +. .ci/common.sh + +check_platform + function cleanup { sleep 1 pkill -9 rv32emu @@ -8,9 +12,9 @@ function cleanup { function ASSERT { $* local RES=$? - if [ $RES -ne 0 ]; then + if [ ${RES} -ne 0 ]; then echo 'Assert failed: "' $* '"' - exit $RES + exit ${RES} fi } @@ -18,61 +22,88 @@ cleanup ENABLE_VBLK=1 VBLK_IMG=build/disk.img -which dd >/dev/null 2>&1 || ENABLE_VBLK=0 -which mkfs.ext4 >/dev/null 2>&1 || which $(brew --prefix e2fsprogs)/sbin/mkfs.ext4 >/dev/null 2>&1 || ENABLE_VBLK=0 -which 7z >/dev/null 2>&1 || ENABLE_VBLK=0 +[ -f "${VBLK_IMG}" ] || ENABLE_VBLK=0 TIMEOUT=50 -OPTS=" -k build/linux-image/Image " -OPTS+=" -i build/linux-image/rootfs.cpio " -if [ "$ENABLE_VBLK" -eq "1" ]; then - dd if=/dev/zero of=$VBLK_IMG bs=4M count=32 - mkfs.ext4 $VBLK_IMG || $(brew --prefix e2fsprogs)/sbin/mkfs.ext4 $VBLK_IMG - OPTS+=" -x vblk:$VBLK_IMG " -else - printf "Virtio-blk Test...Passed\n" -fi -RUN_LINUX="build/rv32emu ${OPTS}" +OPTS_BASE=" -k build/linux-image/Image" +OPTS_BASE+=" -i build/linux-image/rootfs.cpio" -if [ "$ENABLE_VBLK" -eq "1" ]; then -ASSERT expect < mnt/emu.txt\n" } timeout { exit 3 } -expect "# " { send "sync\n" } timeout { exit 3 } -expect "# " { send "umount mnt\n" } timeout { exit 3 } -expect "# " { send "\x01"; send "x" } timeout { exit 3 } -DONE -else -ASSERT expect </dev/null 2>&1 || ret=4 - printf "Virtio-blk Test: [ ${MESSAGES[$ret]}${COLOR_N} ]\n" +if [ "${ENABLE_VBLK}" -eq "1" ]; then + # Read-only + TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${VBLK_IMG},readonly") + EXPECT_CMDS+=(' + expect "buildroot login:" { send "root\n" } timeout { exit 1 } + expect "# " { send "uname -a\n" } timeout { exit 2 } + expect "riscv32 GNU/Linux" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } + expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 } + expect -ex "-sh: can'\''t create mnt/emu.txt: Read-only file system" {} timeout { exit 3 } + expect "# " { send "\x01"; send "x" } timeout { exit 3 } + ') + + # Read-write using disk image + TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${VBLK_IMG}") + VBLK_EXPECT_CMDS=' + expect "buildroot login:" { send "root\n" } timeout { exit 1 } + expect "# " { send "uname -a\n" } timeout { exit 2 } + expect "riscv32 GNU/Linux" { send "mkdir mnt && mount /dev/vda mnt\n" } timeout { exit 3 } + expect "# " { send "echo rv32emu > mnt/emu.txt\n" } timeout { exit 3 } + expect "# " { send "sync\n" } timeout { exit 3 } + expect "# " { send "umount mnt\n" } timeout { exit 3 } + expect "# " { send "\x01"; send "x" } timeout { exit 3 } + ' + EXPECT_CMDS+=("${VBLK_EXPECT_CMDS}") + + # Read-write using /dev/loopx(Linux) or /dev/diskx(Darwin) block device + TEST_OPTIONS+=("${OPTS_BASE} -x vblk:${BLK_DEV}") + EXPECT_CMDS+=("${VBLK_EXPECT_CMDS}") fi +for i in "${!TEST_OPTIONS[@]}"; do + printf "${COLOR_Y}===== Test option: ${TEST_OPTIONS[$i]} =====${COLOR_N}\n" + + OPTS="${OPTS_BASE}" + # No need to add option when running base test + if [[ ! "${TEST_OPTIONS[$i]}" =~ "base" ]]; then + OPTS+="${TEST_OPTIONS[$i]}" + fi + RUN_LINUX="build/rv32emu ${OPTS}" + + ASSERT expect <<-DONE + set timeout ${TIMEOUT} + spawn ${RUN_LINUX} + ${EXPECT_CMDS[$i]} + DONE + + ret=$? + cleanup + + printf "\nBoot Linux Test: [ ${MESSAGES[$ret]}${COLOR_N} ]\n" + if [[ "${TEST_OPTIONS[$i]}" =~ vblk ]]; then + # read-only test first, so the emu.txt definitely does not exist, skipping the check + if [[ ! "${TEST_OPTIONS[$i]}" =~ readonly ]]; then + 7z l ${VBLK_IMG} | grep emu.txt >/dev/null 2>&1 || ret=4 + fi + printf "Virtio-blk Test: [ ${MESSAGES[$ret]}${COLOR_N} ]\n" + fi +done + exit ${ret} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7a4fbd52..b5ce486a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -65,7 +65,14 @@ jobs: actions-cache-folder: 'emsdk-cache' - name: Set parallel jobs variable run: | - echo "PARALLEL=-j$(nproc)" >> $GITHUB_ENV + echo "PARALLEL=-j$(nproc)" >> "$GITHUB_ENV" + echo "BOOT_LINUX_TEST=TMP_FILE=\$(mktemp "$RUNNER_TEMP/tmpfile.XXXXXX"); \ + sudo env TMP_FILE=\${TMP_FILE} .ci/boot-linux-prepare.sh setup; \ + . \${TMP_FILE}; \ + .ci/boot-linux.sh; \ + EXIT_CODE=\$?; \ + sudo env TMP_FILE=\${TMP_FILE} BLK_DEV=\${BLK_DEV} .ci/boot-linux-prepare.sh cleanup; \ + exit \${EXIT_CODE};" >> "$GITHUB_ENV" - name: fetch artifact first to reduce HTTP requests env: CC: ${{ steps.install_cc.outputs.cc }} @@ -265,7 +272,7 @@ jobs: CC: ${{ steps.install_cc.outputs.cc }} run: | make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 $PARALLEL && make ENABLE_SYSTEM=1 artifact $PARALLEL - .ci/boot-linux.sh + bash -c "${BOOT_LINUX_TEST}" make ENABLE_SYSTEM=1 clean if: ${{ always() }} - name: boot Linux kernel test (JIT) @@ -273,7 +280,7 @@ jobs: CC: ${{ steps.install_cc.outputs.cc }} run: | make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_T2C=0 ENABLE_MOP_FUSION=0 $PARALLEL && make ENABLE_SYSTEM=1 artifact $PARALLEL - .ci/boot-linux.sh + bash -c "${BOOT_LINUX_TEST}" make ENABLE_SYSTEM=1 ENABLE_JIT=1 ENABLE_T2C=0 ENABLE_MOP_FUSION=0 clean if: ${{ always() }} - name: Architecture test @@ -292,7 +299,7 @@ jobs: uses: actions/checkout@v4 - name: Set parallel jobs variable run: | - echo "PARALLEL=-j$(nproc)" >> $GITHUB_ENV + echo "PARALLEL=-j$(nproc)" >> "$GITHUB_ENV" - name: build artifact # The GitHub Action for non-x86 CPU uses: allinurl/run-on-arch-action@master @@ -351,7 +358,14 @@ jobs: actions-cache-folder: 'emsdk-cache' - name: Set parallel jobs variable run: | - echo "PARALLEL=-j$(sysctl -n hw.logicalcpu)" >> $GITHUB_ENV + echo "PARALLEL=-j$(sysctl -n hw.logicalcpu)" >> "$GITHUB_ENV" + echo "BOOT_LINUX_TEST=TMP_FILE=\$(mktemp "$RUNNER_TEMP/tmpfile.XXXXXX"); \ + sudo env TMP_FILE=\${TMP_FILE} .ci/boot-linux-prepare.sh setup; \ + . \${TMP_FILE}; \ + .ci/boot-linux.sh; \ + EXIT_CODE=\$?; \ + sudo env TMP_FILE=\${TMP_FILE} BLK_DEV=\${BLK_DEV} .ci/boot-linux-prepare.sh cleanup; \ + exit \${EXIT_CODE};" >> "$GITHUB_ENV" - name: Symlink gcc-14 due to the default /usr/local/bin/gcc links to system's clang run: | ln -s /opt/homebrew/opt/gcc/bin/gcc-14 /usr/local/bin/gcc-14 @@ -463,7 +477,7 @@ jobs: run: | make distclean && make INITRD_SIZE=32 ENABLE_SYSTEM=1 $PARALLEL && \ make ENABLE_SYSTEM=1 artifact $PARALLEL - .ci/boot-linux.sh + bash -c "${BOOT_LINUX_TEST}" make ENABLE_SYSTEM=1 clean if: ${{ always() }} - name: Architecture test