diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4af80c298d..4a8033a2c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -117,6 +117,9 @@ jobs: run-x86_64: name: Run Hermit for Rust (x86_64) runs-on: ubuntu-latest + defaults: + run: + working-directory: kernel steps: - name: Checkout hermit-rs uses: actions/checkout@v4 @@ -125,6 +128,7 @@ jobs: submodules: true - name: Remove hermit-kernel submodule run: git rm -r kernel + working-directory: . - name: Checkout hermit-kernel uses: actions/checkout@v4 with: @@ -146,131 +150,31 @@ jobs: file: rusty-loader-x86_64 - name: Install virtiofsd run: cargo install virtiofsd - - name: Build dev profile - run: cargo build -Zbuild-std=std,panic_abort --package rusty_demo --target x86_64-unknown-hermit --features pci-ids - - name: Test dev profile - run: | - mkdir -p foo - virtiofsd --socket-path=./vhostqemu --shared-dir ./foo --announce-submounts --sandbox none --seccomp none --inode-file-handles=never & - qemu-system-x86_64 -display none -smp 1 -m 1G -serial stdio \ - -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 \ - -kernel rusty-loader-x86_64 \ - -chardev socket,id=char0,path=./vhostqemu \ - -device vhost-user-fs-pci,queue-size=1024,chardev=char0,tag=root \ - -object memory-backend-file,id=mem,size=1G,mem-path=/dev/shm,share=on -numa node,memdev=mem \ - -initrd target/x86_64-unknown-hermit/debug/rusty_demo - - name: Build release profile - run: cargo build -Zbuild-std=std,panic_abort --package rusty_demo --target x86_64-unknown-hermit --release --features pci-ids - - name: Test release profile - run: | - mkdir -p foo - virtiofsd --socket-path=./vhostqemu --shared-dir ./foo --announce-submounts --sandbox none --seccomp none --inode-file-handles=never & - qemu-system-x86_64 -display none -smp 1 -m 1G -serial stdio \ - -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 \ - -kernel rusty-loader-x86_64 \ - -chardev socket,id=char0,path=./vhostqemu \ - -device vhost-user-fs-pci,queue-size=1024,chardev=char0,tag=root \ - -object memory-backend-file,id=mem,size=1G,mem-path=/dev/shm,share=on -numa node,memdev=mem \ - -initrd target/x86_64-unknown-hermit/release/rusty_demo - - name: Build httpd with DHCP support (debug, rtl8139) - run: cargo build -Zbuild-std=std,panic_abort --target x86_64-unknown-hermit --package httpd --features ci,dhcpv4,rtl8139 - - name: Test httpd with DHCP support (debug, rtl8139) - run: | - qemu-system-x86_64 -smp 1 -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr,rdrand \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none -m 128M -serial stdio \ - -kernel rusty-loader-x86_64 \ - -initrd target/x86_64-unknown-hermit/debug/httpd \ - -netdev user,id=u1,hostfwd=tcp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9 \ - -device rtl8139,netdev=u1 & - sleep 5 - curl http://127.0.0.1:9975/help - sleep 1 - - name: Build httpd with DHCP support (debug, virtio-net) - run: cargo build -Zbuild-std=std,panic_abort --target x86_64-unknown-hermit --package httpd --features ci,dhcpv4 - - name: Test httpd with DHCP support (debug, virtio-net) - run: | - qemu-system-x86_64 -smp 1 -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr,rdrand \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none -m 512M -serial stdio \ - -kernel rusty-loader-x86_64 \ - -initrd target/x86_64-unknown-hermit/debug/httpd \ - -netdev user,id=u1,hostfwd=tcp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9 \ - -device virtio-net-pci,netdev=u1,disable-legacy=on & - sleep 5 - curl http://127.0.0.1:9975/help - sleep 1 - - name: Build httpd with DHCP support (release, rtl8139) - run: cargo build -Zbuild-std=std,panic_abort --target x86_64-unknown-hermit --package httpd --release --features ci,dhcpv4,rtl8139 - - name: Test httpd with DHCP support (release, rtl8139) - run: | - qemu-system-x86_64 -smp 1 -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr,rdrand \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none -m 128M -serial stdio \ - -kernel rusty-loader-x86_64 \ - -initrd target/x86_64-unknown-hermit/release/httpd \ - -netdev user,id=u1,hostfwd=tcp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9 \ - -device rtl8139,netdev=u1 & - sleep 5 - curl http://127.0.0.1:9975/help - sleep 1 - - name: Build httpd with DHCP support (release, virtio-net) - run: cargo build -Zbuild-std=std,panic_abort --target x86_64-unknown-hermit --package httpd --release --features ci,dhcpv4 - - name: Test httpd with DHCP support (release, virtio-net) - run: | - qemu-system-x86_64 -smp 1 -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr,rdrand \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none -m 512M -serial stdio \ - -kernel rusty-loader-x86_64 \ - -initrd target/x86_64-unknown-hermit/release/httpd \ - -netdev user,id=u1,hostfwd=tcp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9 \ - -device virtio-net-pci,netdev=u1,disable-legacy=on & - sleep 5 - curl http://127.0.0.1:9975/help - sleep 1 - - name: Build minimal profile - run: cargo build -Zbuild-std=std,panic_abort --target x86_64-unknown-hermit --no-default-features --release --package hello_world - - name: Test minimal profile - run: | - FREQ=`grep 'cpu MHz' /proc/cpuinfo | head -1 | awk -F: '{print $2}' | awk '{printf("%d\n",$1 + 0.5)}'` - echo "FREQ = $FREQ" - qemu-system-x86_64 \ - -M microvm,x-option-roms=off,pit=off,pic=off,rtc=on \ - -global virtio-mmio.force-legacy=on -nodefaults -no-user-config \ - -display none -smp 1 -m 64M -serial stdio \ - -kernel rusty-loader-x86_64 \ - -initrd target/x86_64-unknown-hermit/release/hello_world \ - -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 \ - -append "-freq $FREQ" \ - || qemu_status=$? - test $qemu_status -eq 3 - - name: Build udp tests (debug, virtio-net) - run: cargo build -Zbuild-std=std,panic_abort --target x86_64-unknown-hermit --package testudp --features udp,dhcpv4 - - name: Test udp profile - run: | - qemu-system-x86_64 -smp 1 -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr,rdrand \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none -m 512M -serial stdio \ - -kernel rusty-loader-x86_64 \ - -initrd target/x86_64-unknown-hermit/debug/testudp \ - -netdev user,id=u1,hostfwd=udp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9 \ - -device virtio-net-pci,netdev=u1,disable-legacy=on & - sleep 5 - echo "exit" | socat -d -d -d - UDP:localhost:9975 - - name: Build udp tests (release, virtio-net) - run: cargo build -Zbuild-std=std,panic_abort --release --target x86_64-unknown-hermit --package testudp --features udp,dhcpv4 - - name: Test udp profile - run: | - qemu-system-x86_64 -smp 1 -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr,rdrand \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none -m 512M -serial stdio \ - -kernel rusty-loader-x86_64 \ - -initrd target/x86_64-unknown-hermit/release/testudp \ - -netdev user,id=u1,hostfwd=udp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9 \ - -device virtio-net-pci,netdev=u1,disable-legacy=on & - sleep 5 - echo "exit" | socat -d -d -d - UDP:localhost:9975 + - name: rusty_demo with pci-ids and virtiofsd + run: cargo xtask ci qemu --arch x86_64 --package rusty_demo --features pci-ids --virtiofsd + - name: rusty_demo with pci-ids and virtiofsd (release) + run: cargo xtask ci qemu --arch x86_64 --package rusty_demo --features pci-ids --virtiofsd --release + - name: httpd with virtio-net-pci and dhcpv4 + run: cargo xtask ci qemu --arch x86_64 --package httpd --features ci,dhcpv4 --netdev virtio-net-pci + - name: httpd with virtio-net-pci and dhcpv4 (release) + run: cargo xtask ci qemu --arch x86_64 --package httpd --features ci,dhcpv4 --netdev virtio-net-pci --release + - name: httpd with rtl8139 and dhcpv4 + run: cargo xtask ci qemu --arch x86_64 --package httpd --features ci,dhcpv4,rtl8139 --netdev rtl8139 + - name: httpd with rtl8139 and dhcpv4 (release) + run: cargo xtask ci qemu --arch x86_64 --package httpd --features ci,dhcpv4,rtl8139 --netdev rtl8139 --release + - name: hello_world on microVM (release) + run: cargo xtask ci qemu --arch x86_64 --package hello_world --no-default-features --microvm --release + - name: testudp with virtio-net-pci and dhcpv4 + run: cargo xtask ci qemu --arch x86_64 --package testudp --features udp,dhcpv4 --netdev virtio-net-pci + - name: testudp with virtio-net-pci and dhcpv4 (release) + run: cargo xtask ci qemu --arch x86_64 --package testudp --features udp,dhcpv4 --netdev virtio-net-pci --release run-aarch64: name: Run Hermit for Rust (aarch64) runs-on: ubuntu-latest + defaults: + run: + working-directory: kernel steps: - name: Checkout hermit-rs uses: actions/checkout@v4 @@ -279,6 +183,7 @@ jobs: submodules: true - name: Remove hermit-kernel submodule run: git rm -r kernel + working-directory: . - name: Checkout hermit-kernel uses: actions/checkout@v4 with: @@ -299,52 +204,21 @@ jobs: . kernel kernel/hermit-builtins - - name: Build dev profile - run: cargo build -Zbuild-std=std,panic_abort --target aarch64-unknown-hermit --package rusty_demo --features pci-ids - - name: Test dev kernel - run: | - qemu-system-aarch64 -semihosting \ - -kernel rusty-loader-aarch64 -machine virt,gic-version=3 \ - -m 512M -cpu cortex-a72 -smp 1 -display none -serial stdio \ - -device guest-loader,addr=0x48000000,initrd=target/aarch64-unknown-hermit/debug/rusty_demo - - name: Build release profile - run: cargo build -Zbuild-std=std,panic_abort --target aarch64-unknown-hermit --package rusty_demo --release --features pci-ids - - name: Test release kernel - run: | - qemu-system-aarch64 -semihosting \ - -kernel rusty-loader-aarch64 -machine virt,gic-version=3 \ - -m 512M -cpu cortex-a72 -smp 1 -display none -serial stdio \ - -device guest-loader,addr=0x48000000,initrd=target/aarch64-unknown-hermit/release/rusty_demo - - name: Build httpd with DHCP support (debug) - run: cargo build -Zbuild-std=std,panic_abort --target aarch64-unknown-hermit --package httpd --features ci,dhcpv4 - - name: Test httpd with DHCP support (debug, virtio-net) - run: | - qemu-system-aarch64 -semihosting \ - -kernel rusty-loader-aarch64 -machine virt,gic-version=3 \ - -m 512M -cpu cortex-a72 -smp 1 -display none -serial stdio \ - -device guest-loader,addr=0x48000000,initrd=target/aarch64-unknown-hermit/debug/httpd \ - -netdev user,id=u1,hostfwd=tcp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9 \ - -device virtio-net-pci,netdev=u1,disable-legacy=on & - sleep 5 - curl http://127.0.0.1:9975/help - sleep 1 - - name: Build httpd with DHCP support (release) - run: cargo build -Zbuild-std=std,panic_abort --target aarch64-unknown-hermit --package httpd --release --features ci,dhcpv4 - - name: Test httpd with DHCP support (release, virtio-net) - run: | - qemu-system-aarch64 -semihosting \ - -kernel rusty-loader-aarch64 -machine virt,gic-version=3 \ - -m 512M -cpu cortex-a72 -smp 1 -display none -serial stdio \ - -device guest-loader,addr=0x48000000,initrd=target/aarch64-unknown-hermit/release/httpd \ - -netdev user,id=u1,hostfwd=tcp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9 \ - -device virtio-net-pci,netdev=u1,disable-legacy=on & - sleep 5 - curl http://127.0.0.1:9975/help - sleep 1 + - name: rusty_demo with pci-ids + run: cargo xtask ci qemu --arch aarch64 --package rusty_demo --features pci-ids + - name: rusty_demo with pci-ids (release) + run: cargo xtask ci qemu --arch aarch64 --package rusty_demo --features pci-ids --release + - name: httpd with dhcpv4 + run: cargo xtask ci qemu --arch aarch64 --package httpd --features ci,dhcpv4 --netdev virtio-net-pci + - name: httpd with dhcpv4 (release) + run: cargo xtask ci qemu --arch aarch64 --package httpd --features ci,dhcpv4 --netdev virtio-net-pci --release run-x86_64-kvm: name: Run Hermit for Rust (x86_64 + kvm) runs-on: [self-hosted] + defaults: + run: + working-directory: kernel steps: - name: Checkout hermit-rs uses: actions/checkout@v4 @@ -353,6 +227,7 @@ jobs: submodules: true - name: Remove hermit-kernel submodule run: git rm -r kernel + working-directory: . - name: Checkout hermit-kernel uses: actions/checkout@v4 with: @@ -392,31 +267,13 @@ jobs: - run: cargo install uhyve - uses: mkroening/rust-toolchain-toml@main - uses: Swatinem/rust-cache@v2 - - name: Build dev profile - run: cargo build -Zbuild-std=std,panic_abort --package rusty_demo --target x86_64-unknown-hermit - - name: Test debug version (Uhyve) - run: uhyve --verbose -c 1 target/x86_64-unknown-hermit/debug/rusty_demo - env: - RUST_LOG: debug - - name: Test debug profile (Qemu) - run: | - qemu-system-x86_64 -display none -smp 1 -m 128M -serial stdio \ - -enable-kvm -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr,rdrand \ - -kernel rusty-loader-x86_64 \ - -initrd target/x86_64-unknown-hermit/debug/rusty_demo - - name: Build release profile - run: cargo build -Zbuild-std=std,panic_abort --target x86_64-unknown-hermit --package rusty_demo --release - - name: Test release version (Uhyve) - run: uhyve --verbose -c 1 target/x86_64-unknown-hermit/release/rusty_demo - env: - RUST_LOG: debug - - name: Test release profile (Qemu) - run: | - qemu-system-x86_64 -display none -smp 1 -m 128M -serial stdio \ - -enable-kvm -cpu qemu64,apic,fsgsbase,rdtscp,xsave,xsaveopt,fxsr,rdrand \ - -kernel rusty-loader-x86_64 \ - -initrd target/x86_64-unknown-hermit/release/rusty_demo - - name: Build minimal profile (debug) - run: cargo build -Zbuild-std=std,panic_abort --target x86_64-unknown-hermit --no-default-features --package hello_world - - name: Test debug profile (Firecracker) - run: firecracker --no-api --config-file ./kernel/fc-config.json + - name: rusty_demo on Uhyve + run: cargo xtask ci uhyve --arch x86_64 --package rusty_demo + - name: rusty_demo on Uhyve (release) + run: cargo xtask ci uhyve --arch x86_64 --package rusty_demo --release + - name: rusty_demo on QEMU (with KVM) + run: cargo xtask ci qemu --arch x86_64 --package rusty_demo --accel + - name: rusty_demo on QEMU (with KVM, release) + run: cargo xtask ci qemu --arch x86_64 --package rusty_demo --accel --release + - name: hello_world on Firecracker + run: cargo xtask ci firecracker --arch x86_64 --package hello_world --no-default-features diff --git a/Cargo.lock b/Cargo.lock index 68703c77ae..55aa889711 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,12 @@ dependencies = [ "tock-registers", ] +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "ahash" version = "0.8.3" @@ -116,6 +122,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" + [[package]] name = "bit_field" version = "0.10.2" @@ -134,6 +146,12 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + [[package]] name = "byteorder" version = "1.4.3" @@ -207,12 +225,61 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "critical-section" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.16" @@ -266,6 +333,12 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "embedded-hal" version = "0.2.7" @@ -309,6 +382,16 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +[[package]] +name = "flate2" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "float-cmp" version = "0.9.0" @@ -318,6 +401,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + [[package]] name = "generic_once_cell" version = "0.1.1" @@ -362,7 +454,7 @@ dependencies = [ "atomic-polyfill", "hash32", "rustc_version", - "spin", + "spin 0.9.8", "stable_deref_trait", ] @@ -372,6 +464,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + [[package]] name = "hermit-dtb" version = "0.1.1" @@ -445,6 +543,16 @@ dependencies = [ "x86_64", ] +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "include-transformed" version = "0.2.2" @@ -457,6 +565,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "libc" version = "0.2.147" @@ -503,12 +620,30 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "multiboot" version = "0.8.0" @@ -543,6 +678,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + [[package]] name = "num" version = "0.4.1" @@ -617,6 +761,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -651,6 +805,12 @@ dependencies = [ "bit_field", ] +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + [[package]] name = "pflock" version = "0.2.0" @@ -792,6 +952,28 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.3.5" @@ -801,6 +983,21 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin 0.5.2", + "untrusted", + "web-sys", + "winapi", +] + [[package]] name = "riscv" version = "0.10.1" @@ -834,6 +1031,38 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "rustls" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.4", + "sct", +] + +[[package]] +name = "rustls-webpki" +version = "0.100.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -866,6 +1095,16 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "semver" version = "1.0.18" @@ -904,6 +1143,12 @@ dependencies = [ "managed", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.8" @@ -946,6 +1191,21 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sysinfo" +version = "0.29.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d0e9cc2273cc8d31377bdd638d72e3ac3e5607b18621062b169d02787f1bab" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi", +] + [[package]] name = "take-static" version = "0.1.2" @@ -1013,6 +1273,21 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tock-registers" version = "0.8.1" @@ -1030,12 +1305,60 @@ dependencies = [ "x86", ] +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-ident" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "ureq" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" +dependencies = [ + "base64", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-webpki 0.100.2", + "url", + "webpki-roots", +] + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "utf8parse" version = "0.2.1" @@ -1060,6 +1383,110 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" +dependencies = [ + "rustls-webpki 0.100.2", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" @@ -1172,6 +1599,9 @@ dependencies = [ "clap", "goblin", "llvm-tools", + "sysinfo", + "ureq", + "wait-timeout", "xshell", ] diff --git a/fc-config.json b/fc-config.json deleted file mode 100644 index 71f9f708ed..0000000000 --- a/fc-config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "boot-source": { - "kernel_image_path": "./rusty-loader-x86_64-fc", - "initrd_path": "target/x86_64-unknown-hermit/debug/hello_world", - "boot_args": "" - }, - "drives": [], - "machine-config": { - "vcpu_count": 1, - "mem_size_mib": 256, - "smt": false - } -} diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index cd97c7da52..26dfed366a 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -8,4 +8,7 @@ anyhow = "1.0" clap = { version = "4", features = ["derive"] } goblin = { version = "0.7", default-features = false, features = ["archive", "elf32", "elf64", "std"] } llvm-tools = "0.1" +sysinfo = "0.29" +ureq = "2" +wait-timeout = "0.2" xshell = "0.2" diff --git a/xtask/src/arch.rs b/xtask/src/arch.rs index 8afa88b83a..77f841ab74 100644 --- a/xtask/src/arch.rs +++ b/xtask/src/arch.rs @@ -60,6 +60,19 @@ impl Arch { } } + pub fn ci_cargo_args(&self) -> &'static [&'static str] { + match self { + Arch::X86_64 => &[ + "--target=x86_64-unknown-hermit", + "-Zbuild-std=std,panic_abort", + ], + Arch::Aarch64 => &[ + "--target=aarch64-unknown-hermit", + "-Zbuild-std=std,panic_abort", + ], + } + } + pub fn rustflags(&self) -> &'static [&'static str] { match self { Self::X86_64 => &[], diff --git a/xtask/src/artifact.rs b/xtask/src/artifact.rs index ddb9981fc2..c769c6baa2 100644 --- a/xtask/src/artifact.rs +++ b/xtask/src/artifact.rs @@ -80,4 +80,16 @@ impl Artifact { .collect::() .into() } + + pub fn ci_image(&self, package: &str) -> PathBuf { + [ + "..".as_ref(), + self.target_dir(), + self.arch.hermit_triple().as_ref(), + self.profile_path_component().as_ref(), + package.as_ref(), + ] + .iter() + .collect() + } } diff --git a/xtask/src/ci/build.rs b/xtask/src/ci/build.rs new file mode 100644 index 0000000000..84cd3047a0 --- /dev/null +++ b/xtask/src/ci/build.rs @@ -0,0 +1,45 @@ +use std::path::PathBuf; + +use anyhow::Result; +use clap::Args; +use xshell::cmd; + +use crate::cargo_build::{CargoBuild, CmdExt}; + +/// Build hermit-rs images. +#[derive(Args)] +#[command(next_help_heading = "Build options")] +pub struct Build { + #[command(flatten)] + pub cargo_build: CargoBuild, + + /// Package to build (see `cargo help pkgid`) + #[arg(short, long, id = "SPEC")] + pub package: String, +} + +impl Build { + pub fn run(&self) -> Result<()> { + if super::in_ci() { + eprintln!("::group::cargo build") + } + + let sh = crate::sh()?; + + cmd!(sh, "cargo build --manifest-path ../Cargo.toml") + .args(self.cargo_build.artifact.arch.ci_cargo_args()) + .cargo_build_args(&self.cargo_build) + .args(&["--package", self.package.as_str()]) + .run()?; + + if super::in_ci() { + eprintln!("::endgroup::") + } + + Ok(()) + } + + pub fn image(&self) -> PathBuf { + self.cargo_build.artifact.ci_image(&self.package) + } +} diff --git a/xtask/src/ci/firecracker.rs b/xtask/src/ci/firecracker.rs new file mode 100644 index 0000000000..8f843b7633 --- /dev/null +++ b/xtask/src/ci/firecracker.rs @@ -0,0 +1,42 @@ +use std::path::Path; + +use anyhow::Result; +use clap::Args; +use xshell::cmd; + +use super::build::Build; + +/// Run hermit-rs images on Firecracker. +#[derive(Args)] +pub struct Firecracker { + #[command(flatten)] + build: Build, +} + +impl Firecracker { + pub fn run(self) -> Result<()> { + self.build.run()?; + + let sh = crate::sh()?; + + let config = format!( + include_str!("firecracker_vm_config.json"), + kernel_image_path = "../rusty-loader-x86_64-fc", + initrd_path = self.build.image().display() + ); + eprintln!("firecracker config"); + eprintln!("{config}"); + let config_path = Path::new("firecracker_vm_config.json"); + sh.write_file(config_path, config)?; + + let log_path = Path::new("firecracker.log"); + sh.write_file(log_path, "")?; + cmd!(sh, "firecracker --no-api --config-file {config_path} --log-path {log_path} --level Info --show-level --show-log-origin").run()?; + let log = sh.read_file(log_path)?; + + eprintln!("firecracker log"); + eprintln!("{log}"); + + Ok(()) + } +} diff --git a/xtask/src/ci/firecracker_vm_config.json b/xtask/src/ci/firecracker_vm_config.json new file mode 100644 index 0000000000..14c7b8e29d --- /dev/null +++ b/xtask/src/ci/firecracker_vm_config.json @@ -0,0 +1,13 @@ +{{ + "boot-source": {{ + "kernel_image_path": "{kernel_image_path}", + "initrd_path": "{initrd_path}", + "boot_args": "" + }}, + "drives": [], + "machine-config": {{ + "vcpu_count": 1, + "mem_size_mib": 256, + "smt": false + }} +}} diff --git a/xtask/src/ci/mod.rs b/xtask/src/ci/mod.rs new file mode 100644 index 0000000000..1a497241b3 --- /dev/null +++ b/xtask/src/ci/mod.rs @@ -0,0 +1,31 @@ +use anyhow::Result; +use clap::Subcommand; + +mod build; +mod firecracker; +mod qemu; +mod uhyve; + +/// Run CI tasks. +#[derive(Subcommand)] +pub enum Ci { + Build(build::Build), + Firecracker(firecracker::Firecracker), + Qemu(qemu::Qemu), + Uhyve(uhyve::Uhyve), +} + +impl Ci { + pub fn run(self) -> Result<()> { + match self { + Self::Build(build) => build.run(), + Self::Firecracker(firecracker) => firecracker.run(), + Self::Qemu(qemu) => qemu.run(), + Self::Uhyve(uhyve) => uhyve.run(), + } + } +} + +fn in_ci() -> bool { + std::env::var_os("CI") == Some("true".into()) +} diff --git a/xtask/src/ci/qemu.rs b/xtask/src/ci/qemu.rs new file mode 100644 index 0000000000..704371153a --- /dev/null +++ b/xtask/src/ci/qemu.rs @@ -0,0 +1,286 @@ +use std::net::UdpSocket; +use std::process::{Child, Command, ExitStatus}; +use std::time::Duration; +use std::{env, thread}; + +use anyhow::{bail, ensure, Context, Result}; +use clap::{Args, ValueEnum}; +use sysinfo::{CpuExt, CpuRefreshKind, System, SystemExt}; +use wait_timeout::ChildExt; +use xshell::cmd; + +use super::build::Build; +use crate::arch::Arch; + +/// Run hermit-rs images on QEMU. +#[derive(Args)] +pub struct Qemu { + /// Enable hardware acceleration. + #[arg(long)] + accel: bool, + + /// Enable the `microvm` machine type. + #[arg(long)] + microvm: bool, + + /// Enable a network device. + #[arg(long)] + netdev: Option, + + /// Create multiple vCPUs. + #[arg(long)] + smp: bool, + + /// Enable the `virtiofsd` virtio-fs vhost-user device daemon. + #[arg(long)] + virtiofsd: bool, + + #[command(flatten)] + build: Build, +} + +#[derive(ValueEnum, Clone, Copy)] +pub enum NetworkDevice { + VirtioNetPci, + Rtl8139, +} + +impl Qemu { + pub fn run(self) -> Result<()> { + self.build.run()?; + + let sh = crate::sh()?; + + let virtiofsd = self.virtiofsd.then(spawn_virtiofsd).transpose()?; + thread::sleep(Duration::from_millis(100)); + + let arch = self.build.cargo_build.artifact.arch.name(); + let qemu = env::var_os("QEMU").unwrap_or_else(|| format!("qemu-system-{arch}").into()); + + let qemu = cmd!(sh, "{qemu}") + .args(&["-display", "none"]) + .args(&["-serial", "stdio"]) + .args(&["-kernel", format!("../rusty-loader-{arch}").as_ref()]) + .args(self.machine_args()) + .args(self.cpu_args()) + .args(self.smp_args()) + .args(self.memory_args()) + .args(self.netdev_args()) + .args(self.virtiofsd_args()); + + eprintln!("$ {qemu}"); + let mut qemu = KillChildOnDrop( + Command::from(qemu) + .spawn() + .context("Failed to spawn QEMU")?, + ); + + thread::sleep(Duration::from_millis(100)); + if let Some(status) = qemu.0.try_wait()? { + ensure!(status.qemu_success(), "QEMU exit code: {:?}", status.code()); + } + + match self.build.package.as_str() { + "httpd" => test_httpd()?, + "testudp" => test_testudp()?, + _ => {} + } + + let status = qemu.0.wait_timeout(Duration::from_secs(60 * 2))?; + let Some(status) = status else { + bail!("QEMU timeout") + }; + ensure!(status.qemu_success(), "QEMU exit code: {:?}", status.code()); + + if let Some(mut virtiofsd) = virtiofsd { + let status = virtiofsd.0.wait()?; + assert!(status.success()); + } + + Ok(()) + } + + fn machine_args(&self) -> Vec { + if self.microvm { + let frequency = get_frequency(); + vec![ + "-M".to_string(), + "microvm,x-option-roms=off,pit=off,pic=off,rtc=on".to_string(), + "-global".to_string(), + "virtio-mmio.force-legacy=on".to_string(), + "-nodefaults".to_string(), + "-no-user-config".to_string(), + "-append".to_string(), + format!("-freq {frequency}"), + ] + } else if self.build.cargo_build.artifact.arch == Arch::Aarch64 { + vec!["-machine".to_string(), "virt,gic-version=3".to_string()] + } else { + vec![] + } + } + + fn cpu_args(&self) -> Vec { + match self.build.cargo_build.artifact.arch { + Arch::X86_64 => { + let mut cpu_args = if self.accel { + if cfg!(target_os = "linux") { + vec![ + "-enable-kvm".to_string(), + "-cpu".to_string(), + "host".to_string(), + ] + } else { + todo!() + } + } else { + vec!["-cpu".to_string(), "Skylake-Client".to_string()] + }; + cpu_args.push("-device".to_string()); + cpu_args.push("isa-debug-exit,iobase=0xf4,iosize=0x04".to_string()); + cpu_args.push("-initrd".to_string()); + cpu_args.push(self.build.image().into_os_string().into_string().unwrap()); + cpu_args + } + Arch::Aarch64 => { + let mut cpu_args = if self.accel { + todo!() + } else { + vec!["-cpu".to_string(), "cortex-a72".to_string()] + }; + cpu_args.push("-semihosting".to_string()); + cpu_args.push("-device".to_string()); + cpu_args.push(format!( + "guest-loader,addr=0x48000000,initrd={}", + self.build.image().display() + )); + cpu_args + } + } + } + + fn smp_args(&self) -> &'static [&'static str] { + if self.smp { + &["-smp", "4"] + } else { + &["-smp", "1"] + } + } + + fn memory(&self) -> usize { + let mut memory = 32usize; + if self.build.cargo_build.artifact.profile() == "dev" { + memory *= 4; + } + if self.netdev.is_some() { + memory *= 4; + } + if self.smp { + memory *= 4; + } + if self.build.cargo_build.artifact.arch == Arch::Aarch64 { + memory = memory.max(256); + } + memory + } + + fn memory_args(&self) -> [String; 2] { + ["-m".to_string(), format!("{}M", self.memory())] + } + + fn netdev_args(&self) -> &'static [&'static str] { + match self.netdev { + Some(NetworkDevice::VirtioNetPci) => &[ + "-netdev", + "user,id=u1,hostfwd=tcp::9975-:9975,hostfwd=udp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9", + "-device", + "virtio-net-pci,netdev=u1,disable-legacy=on" + ], + Some(NetworkDevice::Rtl8139) => &[ + "-netdev", + "user,id=u1,hostfwd=tcp::9975-:9975,hostfwd=udp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9", + "-device", + "rtl8139,netdev=u1" + ], + None => &[], + } + } + + fn virtiofsd_args(&self) -> Vec { + if self.virtiofsd { + let memory = self.memory(); + vec![ + "-chardev".to_string(), + "socket,id=char0,path=./vhostqemu".to_string(), + "-device".to_string(), + "vhost-user-fs-pci,queue-size=1024,chardev=char0,tag=root".to_string(), + "-object".to_string(), + format!("memory-backend-file,id=mem,size={memory}M,mem-path=/dev/shm,share=on"), + "-numa".to_string(), + "node,memdev=mem".to_string(), + ] + } else { + vec![] + } + } +} + +fn spawn_virtiofsd() -> Result { + let sh = crate::sh()?; + + sh.create_dir("foo")?; + + let cmd = cmd!(sh, "virtiofsd --socket-path=./vhostqemu --shared-dir ./foo --announce-submounts --sandbox none --seccomp none --inode-file-handles=never"); + + eprintln!("$ {cmd}"); + + Ok(KillChildOnDrop(Command::from(cmd).spawn()?)) +} + +fn get_frequency() -> u64 { + let mut sys = System::new(); + sys.refresh_cpu_specifics(CpuRefreshKind::new().with_frequency()); + let frequency = sys.cpus().first().unwrap().frequency(); + assert!(sys.cpus().iter().all(|cpu| cpu.frequency() == frequency)); + frequency +} + +fn test_httpd() -> Result<()> { + thread::sleep(Duration::from_secs(10)); + eprintln!("[CI] GET http://127.0.0.1:9975"); + let body = ureq::get("http://127.0.0.1:9975") + .timeout(Duration::from_secs(3)) + .call()? + .into_string()?; + eprintln!("[CI] {body}"); + assert_eq!(body.lines().next(), Some("Hello from Hermit! 🦀")); + Ok(()) +} + +fn test_testudp() -> Result<()> { + thread::sleep(Duration::from_secs(10)); + let buf = "exit"; + eprintln!("[CI] send {buf:?} via UDP to 127.0.0.1:9975"); + let socket = UdpSocket::bind("127.0.0.1:0")?; + socket.connect("127.0.0.1:9975")?; + socket.send(buf.as_bytes())?; + Ok(()) +} + +struct KillChildOnDrop(Child); + +impl Drop for KillChildOnDrop { + fn drop(&mut self) { + self.0.kill().ok(); + } +} + +trait ExitStatusExt { + fn qemu_success(&self) -> bool; +} + +impl ExitStatusExt for ExitStatus { + fn qemu_success(&self) -> bool { + self.success() || self.code() == Some(3) + } +} diff --git a/xtask/src/ci/uhyve.rs b/xtask/src/ci/uhyve.rs new file mode 100644 index 0000000000..a26d13daf4 --- /dev/null +++ b/xtask/src/ci/uhyve.rs @@ -0,0 +1,41 @@ +use anyhow::Result; +use clap::Args; +use xshell::cmd; + +use super::build::Build; + +/// Run hermit-rs images on Uhyve. +#[derive(Args)] +pub struct Uhyve { + /// Run with multiple vCPUs. + #[arg(long)] + smp: bool, + + #[command(flatten)] + build: Build, +} + +impl Uhyve { + pub fn run(self) -> Result<()> { + self.build.run()?; + + let sh = crate::sh()?; + + let image = self.build.image(); + + cmd!(sh, "uhyve --verbose {image}") + .env("RUST_LOG", "debug") + .args(self.cpu_count_args()) + .run()?; + + Ok(()) + } + + fn cpu_count_args(&self) -> &'static [&'static str] { + if self.smp { + &["--cpu-count=4"] + } else { + &[] + } + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 0a089c9a4c..133db08239 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -5,6 +5,7 @@ mod archive; mod artifact; mod build; mod cargo_build; +mod ci; mod clippy; use std::path::Path; @@ -16,6 +17,8 @@ use xshell::Shell; #[derive(Parser)] enum Cli { Build(build::Build), + #[command(subcommand)] + Ci(ci::Ci), Clippy(clippy::Clippy), } @@ -23,6 +26,7 @@ impl Cli { fn run(self) -> Result<()> { match self { Self::Build(build) => build.run(), + Self::Ci(ci) => ci.run(), Self::Clippy(clippy) => clippy.run(), } }