diff --git a/.cargo/config.toml b/.cargo/config.toml
new file mode 100644
index 00000000..b1c8f87b
--- /dev/null
+++ b/.cargo/config.toml
@@ -0,0 +1,2 @@
+[target.'cfg(target_os = "macos")']
+runner = "dev/macos-sign-and-run.sh"
diff --git a/.github/workflows/Benchmarks.yml b/.github/workflows/Benchmarks.yml
index f1b53dc6..27b4e529 100644
--- a/.github/workflows/Benchmarks.yml
+++ b/.github/workflows/Benchmarks.yml
@@ -47,7 +47,7 @@ jobs:
steps:
- uses: actions/checkout@v5
- - uses: hyperlight-dev/ci-setup-workflow@v1.8.0
+ - uses: hyperlight-dev/ci-setup-workflow@v2.3.1
with:
rust-toolchain: "1.94"
@@ -58,8 +58,8 @@ jobs:
- name: Download Wasm Modules
uses: actions/download-artifact@v5
with:
- name: guest-modules-lts
- path: ./x64/${{ matrix.config }}
+ name: guest-modules-X64-lts
+ path: ./build/${{ matrix.config }}
### Benchmarks ###
diff --git a/.github/workflows/CreateRelease.yml b/.github/workflows/CreateRelease.yml
index 69170030..46ed14d0 100644
--- a/.github/workflows/CreateRelease.yml
+++ b/.github/workflows/CreateRelease.yml
@@ -36,7 +36,7 @@ jobs:
fetch-depth: 0
# Ensures just is installed using setup wokflow to ensure just version consistency
- name: Hyperlight setup
- uses: hyperlight-dev/ci-setup-workflow@v1.8.0
+ uses: hyperlight-dev/ci-setup-workflow@v2.3.1
with:
rust-toolchain: "1.94"
- name: Set HYPERLIGHTWASM_VERSION
@@ -50,7 +50,7 @@ jobs:
- name: Download Wasm Modules
uses: actions/download-artifact@v5
with:
- name: guest-modules-lts
+ name: guest-modules-X64-lts
path: ${{ env.PLATFORM }}/${{ env.CONFIG }}
- name: Build rust wasm modules
run: just build-rust-wasm-examples ${{ env.CONFIG }}
diff --git a/.github/workflows/dep_build_wasm_examples.yml b/.github/workflows/dep_build_wasm_examples.yml
index 31ebd609..f0f8e324 100644
--- a/.github/workflows/dep_build_wasm_examples.yml
+++ b/.github/workflows/dep_build_wasm_examples.yml
@@ -23,6 +23,15 @@ permissions:
jobs:
build-docker-image:
if: ${{ inputs.docs_only == 'false' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
+ strategy:
+ matrix:
+ arch:
+ - name: X64
+ runner: ubuntu-latest
+ docker-platform: linux/amd64
+ - name: arm64
+ runner: ubuntu-24.04-arm
+ docker-platform: linux/arm64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
@@ -46,15 +55,18 @@ jobs:
with:
images: ${{ github.repository_owner }}/wasm-clang-builder
- name: Calculate ghcr cache destination
+ id: ghcr-dest
env:
CAN_WRITE: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) && github.actor != 'dependabot[bot]' }}
run: |
if [ "$CAN_WRITE" = "true" ]; then
echo "CACHE_TO=type=registry,ref=ghcr.io/${{ github.repository_owner }}/wasm-clang-builder:buildcache,mode=max" >> $GITHUB_ENV
echo "DO_PUSH=true" >> $GITHUB_ENV
+ echo "DO_PUSH=true" >> $GITHUB_OUTPUT
else
echo "CACHE_TO=type=local,dest=/tmp/wasm-clang-builder-cache/" >> $GITHUB_ENV
echo "DO_PUSH=false" >> $GITHUB_ENV
+ echo "DO_PUSH=false" >> $GITHUB_OUTPUT
fi
- name: Build and push wasm-clang-builder
# Only push if not from a fork, not from pull request, and not from dependabot
@@ -67,13 +79,36 @@ jobs:
build-args: |
WASI_SDK_VERSION_FULL=25.0
GCC_VERSION=12
- tags: ghcr.io/${{ github.repository_owner }}/wasm-clang-builder:latest
+ platforms: ${{ matrix.arch.docker-platform }}
+ tags: ghcr.io/${{ github.repository_owner }}/wasm-clang-builder:latest-${{ matrix.arch.name }}
cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/wasm-clang-builder:buildcache
cache-to: ${{ env.CACHE_TO }}
+ outputs:
+ do_push: ${{ steps.ghcr-dest.outputs.DO_PUSH }}
- build-wasm-examples:
+ merge-docker-image:
needs: build-docker-image
+ if: ${{ needs.build-docker-image.outputs.do_push == 'true' }}
runs-on: ubuntu-latest
+ steps:
+ - name: Login to Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Create manifest
+ run: |
+ docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/wasm-clang-builder:latest \
+ ghcr.io/${{ github.repository_owner }}/wasm-clang-builder:latest-X64 \
+ ghcr.io/${{ github.repository_owner }}/wasm-clang-builder:latest-arm64
+
+ build-wasm-examples:
+ needs: merge-docker-image
+ # Required because merge-docker-image is skipped on some runs,
+ # and a skipped dependency transitively skips all downstream
+ # jobs. See: https://github.com/actions/runner/issues/2205
+ if: ${{ !cancelled() && !failure() }}
strategy:
matrix:
wasmtime_version:
@@ -81,14 +116,24 @@ jobs:
features: ""
- name: latest
features: "wasmtime_latest"
+ arch:
+ - name: X64
+ runner: ubuntu-latest
+ - name: arm64
+ runner: ubuntu-24.04-arm
+ runs-on: ${{ matrix.arch.runner }}
+ env:
+ CI_BUILD_WASM_MODULES: true
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Remove default clang
run: sudo rm /usr/bin/clang
+ - name: Fake /dev/kvm for ci-setup-workflow action
+ run: sudo touch /dev/kvm
- name: Hyperlight setup workflow
- uses: hyperlight-dev/ci-setup-workflow@v1.8.0
+ uses: hyperlight-dev/ci-setup-workflow@v2.3.1
with:
rust-toolchain: "1.94"
- name: Set up Docker Buildx
@@ -110,6 +155,6 @@ jobs:
- name: Upload Wasm Modules (wasmtime ${{ matrix.wasmtime_version.name }})
uses: actions/upload-artifact@v4
with:
- name: guest-modules-${{ matrix.wasmtime_version.name }}
+ name: guest-modules-${{ matrix.arch.name }}-${{ matrix.wasmtime_version.name }}
path: |
- x64/release/*.aot
+ build/release/*.aot
diff --git a/.github/workflows/dep_cargo_publish.yml b/.github/workflows/dep_cargo_publish.yml
index a99109f6..4b000698 100644
--- a/.github/workflows/dep_cargo_publish.yml
+++ b/.github/workflows/dep_cargo_publish.yml
@@ -20,7 +20,7 @@ jobs:
fetch-tags: true
- name: Hyperlight setup
- uses: hyperlight-dev/ci-setup-workflow@v1.8.0
+ uses: hyperlight-dev/ci-setup-workflow@v2.3.1
with:
rust-toolchain: "1.94"
diff --git a/.github/workflows/dep_rust.yml b/.github/workflows/dep_rust.yml
index 98bc3db5..54c4423c 100644
--- a/.github/workflows/dep_rust.yml
+++ b/.github/workflows/dep_rust.yml
@@ -39,25 +39,54 @@ jobs:
# failed-job rerun does not need to repeat the entire matrix.
fail-fast: false
matrix:
- hypervisor: [hyperv, mshv3, kvm] # hyperv is windows, mshv and kvm are linux
- cpu: [amd, intel]
+ hypervisor: [hyperv, mshv3, kvm, hvf] # hyperv is windows, mshv and kvm are linux
+ cpu: [amd, intel, apple, microsoft]
+ arch: [X64, arm64]
config: [debug, release]
wasmtime: [latest, lts]
exclude:
# Latest testing: skip debug builds to reduce CI load
- wasmtime: latest
config: debug
-
- runs-on: ${{ fromJson(
- format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}", "JobId=build-{3}-{4}-{5}-{6}-{7}"]',
- matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux',
- matrix.hypervisor == 'hyperv' && 'win2025' || matrix.hypervisor == 'mshv3' && 'azlinux3-mshv' || matrix.hypervisor,
- matrix.cpu,
- matrix.config,
- matrix.wasmtime,
- github.run_id,
- github.run_number,
- github.run_attempt)) }}
+ - cpu: apple
+ hypervisor: hyperv
+ - cpu: apple
+ hypervisor: mshv3
+ - cpu: microsoft
+ hypervisor: mshv3
+ - cpu: microsoft
+ hypervisor: kvm
+ - cpu: microsoft
+ hypervisor: hvf
+ - arch: X64
+ hypervisor: hvf
+ - cpu: amd
+ arch: arm64
+ - cpu: intel
+ arch: arm64
+ - cpu: apple
+ arch: X64
+ - cpu: microsoft
+ arch: X64
+ runs-on: ${{ fromJson(matrix.arch == 'X64'
+ && format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}", "JobId=build-{3}-{4}-{5}-{6}-{7}"]',
+ matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux',
+ matrix.hypervisor == 'hyperv' && 'win2025' || matrix.hypervisor == 'mshv3' && 'azlinux3-mshv' || matrix.hypervisor,
+ matrix.cpu,
+ matrix.config,
+ matrix.wasmtime,
+ github.run_id,
+ github.run_number,
+ github.run_attempt)
+ || matrix.hypervisor == 'hyperv'
+ && format('["self-hosted", "Windows", "ARM64", "1ES.Pool=hl-windows-arm", "JobId=build-{0}-{1}-{2}-{3}"]',
+ matrix.config,
+ github.run_id,
+ github.run_number,
+ github.run_attempt)
+ || format('["self-hosted", "{0}", "arm64", "{1}"]',
+ matrix.hypervisor == 'hvf' && 'macos' || 'Linux',
+ matrix.hypervisor)) }}
env:
# Features to pass to cargo.
# On Windows LTS builds, do not pass any features.
@@ -65,13 +94,16 @@ jobs:
# On Linux, always pass the hypervisor feature (kvm/mshv3).
# On Linux latest builds, also add wasmtime_latest.
FEATURES: ${{ matrix.hypervisor != 'hyperv' && format('{0}{1}', matrix.hypervisor, matrix.wasmtime == 'latest' && ',wasmtime_latest' || '') || (matrix.wasmtime == 'latest' && 'wasmtime_latest' || '') }}
+ JUST_OVERRIDE_ARCH: ${{ matrix.arch == 'X64' && 'x86_64' || 'aarch64' }}
steps:
- uses: actions/checkout@v5
- name: Hyperlight setup
- uses: hyperlight-dev/ci-setup-workflow@v1.8.0
+ uses: hyperlight-dev/ci-setup-workflow@v2.3.1
with:
rust-toolchain: "1.94"
+ additional-toolchain-directory: src/tests/rust_guests
+ just-version: 1.59.0
- name: Add Nightly Rust
run: |
@@ -86,11 +118,32 @@ jobs:
if: runner.os == 'Windows'
run: rustup component add --toolchain nightly-x86_64-pc-windows-msvc rustfmt
+ - name: Configure ARM64 libclang
+ if: runner.os == 'Windows' && matrix.arch == 'arm64'
+ shell: pwsh
+ run: |
+ if (-not $env:VSINSTALLDIR) {
+ throw "Visual Studio developer environment did not set VSINSTALLDIR"
+ }
+ $libclang = Join-Path $env:VSINSTALLDIR "VC\Tools\Llvm\ARM64\bin\libclang.dll"
+ if (-not (Test-Path $libclang)) {
+ throw "ARM64 libclang not found at '$libclang'"
+ }
+ $llvmPath = Split-Path $libclang
+ "LIBCLANG_PATH=$llvmPath" >> $env:GITHUB_ENV
+ $llvmPath >> $env:GITHUB_PATH
+
+ - name: Install clang tools (macOS)
+ if: ${{ runner.os == 'macOS' }}
+ run: |
+ brew install llvm
+ echo "$(brew --prefix llvm)/bin" >> "$GITHUB_PATH"
+
- name: Download Wasm Modules
uses: actions/download-artifact@v5
with:
- name: guest-modules-${{ matrix.wasmtime }}
- path: ./x64/${{ matrix.config }}
+ name: guest-modules-${{ matrix.arch }}-${{ matrix.wasmtime }}
+ path: ./build/${{ matrix.config }}
- name: Build Rust component model examples
run: |
@@ -144,38 +197,76 @@ jobs:
strategy:
fail-fast: false
matrix:
- hypervisor: [hyperv, mshv3, kvm]
- cpu: [amd, intel]
+ hypervisor: [hyperv, mshv3, kvm, hvf]
+ cpu: [amd, intel, apple, microsoft]
+ arch: [X64, arm64]
wasmtime: [lts]
+ exclude:
+ # Latest testing: skip debug builds to reduce CI load
+ - cpu: apple
+ hypervisor: hyperv
+ - cpu: apple
+ hypervisor: mshv3
+ - cpu: microsoft
+ hypervisor: mshv3
+ - cpu: microsoft
+ hypervisor: kvm
+ - cpu: microsoft
+ hypervisor: hvf
+ - arch: X64
+ hypervisor: hvf
+ - cpu: amd
+ arch: arm64
+ - cpu: intel
+ arch: arm64
+ - cpu: apple
+ arch: X64
+ - cpu: microsoft
+ arch: X64
include:
- hypervisor: kvm
cpu: amd
+ arch: X64
wasmtime: latest
- runs-on: ${{ fromJson(
- format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}", "JobId=benchmark-{3}-{4}-{5}-{6}"]',
- matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux',
- matrix.hypervisor == 'hyperv' && 'win2025' || matrix.hypervisor == 'mshv3' && 'azlinux3-mshv' || matrix.hypervisor,
- matrix.cpu,
- matrix.wasmtime,
- github.run_id,
- github.run_number,
- github.run_attempt)) }}
+ runs-on: ${{ fromJson(matrix.arch == 'X64'
+ && format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-{2}", "JobId=benchmark-{3}-{4}-{5}-{6}"]',
+ matrix.hypervisor == 'hyperv' && 'Windows' || 'Linux',
+ matrix.hypervisor == 'hyperv' && 'win2025' || matrix.hypervisor == 'mshv3' && 'azlinux3-mshv' || matrix.hypervisor,
+ matrix.cpu,
+ matrix.wasmtime,
+ github.run_id,
+ github.run_number,
+ github.run_attempt)
+ || matrix.hypervisor == 'hyperv'
+ && format('["self-hosted", "Windows", "ARM64", "1ES.Pool=hl-windows-arm", "JobId=build-{0}-{1}-{2}"]',
+ github.run_id,
+ github.run_number,
+ github.run_attempt)
+ || format('["self-hosted", "{0}", "arm64", "{1}"]',
+ matrix.hypervisor == 'hvf' && 'macos' || 'Linux',
+ matrix.hypervisor)) }}
env:
FEATURES: ${{ matrix.hypervisor != 'hyperv' && format('{0}{1}', matrix.hypervisor, matrix.wasmtime == 'latest' && ',wasmtime_latest' || '') || (matrix.wasmtime == 'latest' && 'wasmtime_latest' || '') }}
steps:
- uses: actions/checkout@v5
- name: Hyperlight setup
- uses: hyperlight-dev/ci-setup-workflow@v1.8.0
+ uses: hyperlight-dev/ci-setup-workflow@v2.3.1
with:
rust-toolchain: "1.94"
+ - name: Install clang tools (macOS)
+ if: ${{ runner.os == 'macOS' }}
+ run: |
+ brew install llvm
+ echo "$(brew --prefix llvm)/bin" >> "$GITHUB_PATH"
+
- name: Download Wasm Modules
uses: actions/download-artifact@v5
with:
- name: guest-modules-${{ matrix.wasmtime }}
- path: ./x64/release
+ name: guest-modules-${{ matrix.arch }}-${{ matrix.wasmtime }}
+ path: ./build/release
- name: Download benchmarks from "latest"
run: just bench-download ${{ runner.os }} ${{ matrix.hypervisor }} ${{ matrix.cpu }} dev-latest
diff --git a/Justfile b/Justfile
index 360bf132..18c0c15c 100644
--- a/Justfile
+++ b/Justfile
@@ -27,8 +27,8 @@ build target=default-target features="": (fmt-check)
cargo build {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--no-default-features -F " + features } }} --verbose --profile={{ if target == "debug" {"dev"} else { target } }}
mkdir-redist target=default-target:
- mkdir {{ mkdir-arg }} x64
- mkdir {{ mkdir-arg }} x64/{{ target }}
+ mkdir {{ mkdir-arg }} build
+ mkdir {{ mkdir-arg }} build/{{ target }}
compile-wit:
wasm-tools component wit ./src/tests/c_guests/wasmsamples/components/runcomponent.wit -w -o ./src/tests/c_guests/wasmsamples/components/runcomponent-world.wasm
@@ -42,28 +42,28 @@ build-wasm-examples target=default-target features="": (compile-wit)
build-rust-wasm-examples target=default-target features="": (mkdir-redist target)
rustup target add wasm32-unknown-unknown
cd ./src/tests/rust_guests/rust_wasm_samples && cargo build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }}
- cargo run -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} ./src/tests/rust_guests/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./x64/{{ target }}/rust_wasm_samples.aot
+ cargo run -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} ./src/tests/rust_guests/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./build/{{ target }}/rust_wasm_samples.aot
build-pulley-rust-wasm-examples target=default-target features="": (mkdir-redist target)
rustup target add wasm32-unknown-unknown
cd ./src/tests/rust_guests/rust_wasm_samples && cargo build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }}
- cargo run -p hyperlight-wasm-aot compile --pulley {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} ./src/tests/rust_guests/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./x64/{{ target }}/rust_wasm_samples.aot
+ cargo run -p hyperlight-wasm-aot compile --pulley {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} ./src/tests/rust_guests/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./build/{{ target }}/rust_wasm_samples.aot
build-rust-component-examples target=default-target features="": (compile-wit)
# use cargo component so we don't get all the wasi imports https://github.com/bytecodealliance/cargo-component?tab=readme-ov-file#relationship-with-wasm32-wasip2
# we also explicitly target wasm32-unknown-unknown since cargo component might try to pull in wasi imports https://github.com/bytecodealliance/cargo-component/issues/290
rustup target add wasm32-unknown-unknown
cd ./src/tests/rust_guests/component_sample && cargo component build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }}
- cargo run -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} --component ./src/tests/rust_guests/component_sample/target/wasm32-unknown-unknown/{{ target }}/component_sample.wasm ./x64/{{ target }}/component_sample.aot
+ cargo run -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} --component ./src/tests/rust_guests/component_sample/target/wasm32-unknown-unknown/{{ target }}/component_sample.wasm ./build/{{ target }}/component_sample.aot
cd ./src/tests/rust_guests/greeter_sample && cargo component build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }}
- cargo run -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} --component ./src/tests/rust_guests/greeter_sample/target/wasm32-unknown-unknown/{{ target }}/greeter_sample.wasm ./x64/{{ target }}/greeter_sample.aot
+ cargo run -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} --component ./src/tests/rust_guests/greeter_sample/target/wasm32-unknown-unknown/{{ target }}/greeter_sample.wasm ./build/{{ target }}/greeter_sample.aot
build-pulley-rust-component-examples target=default-target features="": (compile-wit)
# use cargo component so we don't get all the wasi imports https://github.com/bytecodealliance/cargo-component?tab=readme-ov-file#relationship-with-wasm32-wasip2
# we also explicitly target wasm32-unknown-unknown since cargo component might try to pull in wasi imports https://github.com/bytecodealliance/cargo-component/issues/290
rustup target add wasm32-unknown-unknown
cd ./src/tests/rust_guests/component_sample && cargo component build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }}
- cargo run -p hyperlight-wasm-aot compile --pulley {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} --component ./src/tests/rust_guests/component_sample/target/wasm32-unknown-unknown/{{ target }}/component_sample.wasm ./x64/{{ target }}/component_sample.aot
+ cargo run -p hyperlight-wasm-aot compile --pulley {{ if features =~ "gdb" {"--debug"} else {""} }} {{ if features =~ "wasmtime_latest" {"--wasmtime-version latest"} else {""} }} --component ./src/tests/rust_guests/component_sample/target/wasm32-unknown-unknown/{{ target }}/component_sample.wasm ./build/{{ target }}/component_sample.aot
check target=default-target:
cargo check --profile={{ if target == "debug" {"dev"} else { target } }}
@@ -90,14 +90,24 @@ fmt:
cd src/hyperlight_wasm_runtime && cargo +nightly fmt -v --all
cd src/hyperlight_wasm_macro && cargo +nightly fmt -v --all
+# On Windows runners, GH actions extractions/setup-just installs an
+# amd64 version of just, instead of a native aarch64 version. This
+# seems to be mostly okay, but it means that arch() in the justfile
+# will return x86_64 rather than aarch64. So, in aarch64 CI (where
+# this problem happens) we use an env var to override the arch.
+arch := env("JUST_OVERRIDE_ARCH", arch())
+
+clippy-excluded-features := if arch == "x86_64" { "" } else { "gdb,trace_guest,crashdump" }
+clippy-runtime-features := if arch == "x86_64" { ",gdb,trace_guest" } else { "" }
+
clippy target=default-target: (check target)
- cargo clippy --workspace --exclude hyperlight-wasm-runtime --exclude hyperlight-wasm-macro --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
+ cargo clippy --workspace --exclude hyperlight-wasm-runtime --exclude hyperlight-wasm-macro --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --features "$(cargo metadata --format-version 1 --no-deps | jq -r '[.packages[]|.name as$pkg|.features|keys.[]|select(.!="default" and (IN($ARGS.positional[0]//" "|split(",")[])|not))|$pkg+"/"+.]|join(",")' --args {{clippy-excluded-features}})" -- -D warnings
cd src/tests/rust_guests/rust_wasm_samples && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
cd src/tests/rust_guests/component_sample && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
cd src/tests/rust_guests/greeter_sample && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
# hyperlight_wasm_runtime has mutually exclusive wasmtime features, so we run clippy for each separately with all other features
- cd src/hyperlight_wasm_runtime && cargo hyperlight clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --no-default-features --features wasmtime_latest,gdb,trace_guest,pulley -- -D warnings
- cd src/hyperlight_wasm_runtime && cargo hyperlight clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --no-default-features --features wasmtime_lts,gdb,trace_guest -- -D warnings
+ cd src/hyperlight_wasm_runtime && cargo hyperlight clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --no-default-features --features wasmtime_latest{{clippy-runtime-features}},pulley -- -D warnings
+ cd src/hyperlight_wasm_runtime && cargo hyperlight clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --no-default-features --features wasmtime_lts{{clippy-runtime-features}} -- -D warnings
cd src/hyperlight_wasm_macro && cargo clippy --profile={{ if target == "debug" {"dev"} else { target } }} --all-targets --all-features -- -D warnings
# TESTING
diff --git a/dev/macos-entitlements.plist b/dev/macos-entitlements.plist
new file mode 100644
index 00000000..61eb94d8
--- /dev/null
+++ b/dev/macos-entitlements.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ com.apple.security.hypervisor
+
+
+
diff --git a/dev/macos-sign-and-run.sh b/dev/macos-sign-and-run.sh
new file mode 100755
index 00000000..80d22992
--- /dev/null
+++ b/dev/macos-sign-and-run.sh
@@ -0,0 +1,7 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+
+codesign -f -s - --entitlements "$(dirname "$0")/macos-entitlements.plist" "$1"
+export DYLD_LIBRARY_PATH=$(rustc --print sysroot)/lib/rustlib/aarch64-apple-darwin/lib/
+exec "$@"
diff --git a/docs/wasm-modules-debugging.md b/docs/wasm-modules-debugging.md
index e7a0d7cd..014167c9 100644
--- a/docs/wasm-modules-debugging.md
+++ b/docs/wasm-modules-debugging.md
@@ -39,7 +39,7 @@ After you attach, you can set breakpoints, step through the code, and inspect va
{
"id": "program",
"type": "promptString",
- "default": "x64/debug/hyperlight_wasm_runtime",
+ "default": "build/debug/hyperlight_wasm_runtime",
"description": "Path to the program to debug"
},
],
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index cb763d05..d2e1874d 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,5 +1,4 @@
[toolchain]
-channel = "1.94"
-# Target used for guest binaries. This is an additive list of targets in addition to host platform.
-# Will install the target if not already installed when building guest binaries.
-targets = ["x86_64-unknown-none"]
\ No newline at end of file
+channel = "1.94.1"
+components = ["clippy"]
+targets = ["x86_64-unknown-linux-musl", "wasm32-unknown-unknown"]
\ No newline at end of file
diff --git a/src/examples_common/src/lib.rs b/src/examples_common/src/lib.rs
index 43106eca..9fa49d7c 100644
--- a/src/examples_common/src/lib.rs
+++ b/src/examples_common/src/lib.rs
@@ -20,7 +20,7 @@ use std::path::Path;
use hyperlight_host::{Result, new_error};
/// Get the Wasm module called `name` from the standard module location
-/// at `$REPO_ROOT/x64/[debug|release]/$name`.
+/// at `$REPO_ROOT/build/[debug|release]/$name`.
pub fn get_wasm_module_path(name: &str) -> Result {
#[cfg(debug_assertions)]
let config = "debug";
@@ -32,17 +32,17 @@ pub fn get_wasm_module_path(name: &str) -> Result {
.expect("Failed to get CARGO_MANIFEST_DIR or RUST_DIR_FOR_DEBUGGING_TESTS env var")
});
- let x64_dir = Path::new(&proj_dir)
- .join("../../x64")
+ let build_dir = Path::new(&proj_dir)
+ .join("../../build")
.join(config)
.join(name);
- let path = match x64_dir.canonicalize() {
+ let path = match build_dir.canonicalize() {
Ok(path) => path.to_str().unwrap().to_string(),
Err(e) => {
return Err(new_error!(
"Failed to get the path to the Wasm module: {:?} {}",
- x64_dir,
+ build_dir,
e,
));
}
diff --git a/src/hyperlight_wasm/Cargo.toml b/src/hyperlight_wasm/Cargo.toml
index 70100f95..e5dfe646 100644
--- a/src/hyperlight_wasm/Cargo.toml
+++ b/src/hyperlight_wasm/Cargo.toml
@@ -112,13 +112,14 @@ serde_json = "1.0"
junction = "2"
[features]
-default = ["function_call_metrics", "kvm", "mshv3"]
+default = ["function_call_metrics", "kvm", "mshv3", "hvf"]
function_call_metrics = ["hyperlight-host/function_call_metrics"]
print_debug = ["hyperlight-host/print_debug"]
crashdump = ["hyperlight-host/crashdump"]
gdb = ["hyperlight-host/gdb"]
kvm = ["hyperlight-host/kvm"]
mshv3 = ["hyperlight-host/mshv3"]
+hvf = ["hyperlight-host/hvf"]
pulley = []
trace_guest = ["hyperlight-host/trace_guest"]
# Use latest wasmtime instead of the default LTS version in wasm_runtime
diff --git a/src/hyperlight_wasm/benches/benchmarks.rs b/src/hyperlight_wasm/benches/benchmarks.rs
index 6f5bafb9..91c10eb6 100644
--- a/src/hyperlight_wasm/benches/benchmarks.rs
+++ b/src/hyperlight_wasm/benches/benchmarks.rs
@@ -75,7 +75,7 @@ fn get_loaded_wasm_sandbox() -> LoadedWasmSandbox {
let wasm_sandbox = sandbox.load_runtime().unwrap();
wasm_sandbox
- .load_module("../../x64/release/RunWasm.aot")
+ .load_module("../../build/release/RunWasm.aot")
.unwrap()
}
diff --git a/src/hyperlight_wasm/benches/benchmarks_components.rs b/src/hyperlight_wasm/benches/benchmarks_components.rs
index cdf716ff..da6f0aad 100644
--- a/src/hyperlight_wasm/benches/benchmarks_components.rs
+++ b/src/hyperlight_wasm/benches/benchmarks_components.rs
@@ -93,7 +93,7 @@ fn get_loaded_wasm_sandbox() -> (
let sb = sandbox.load_runtime().unwrap();
let sb = sb
- .load_module("../../x64/release/runcomponent.aot")
+ .load_module("../../build/release/runcomponent.aot")
.unwrap();
(sb, rt)
}
diff --git a/src/hyperlight_wasm/build.rs b/src/hyperlight_wasm/build.rs
index 66b41f63..eda934a2 100644
--- a/src/hyperlight_wasm/build.rs
+++ b/src/hyperlight_wasm/build.rs
@@ -20,7 +20,7 @@ limitations under the License.
// This is done by reading the hyperlight-wasm-runtime binary into a static byte array named WASM_RUNTIME.
// this build script writes the code to do that to a file named built.rs in the OUT_DIR.
// this file is included in lib.rs.
-// The hyperlight-wasm-runtime binary is expected to be in the x64/{config} directory.
+// The hyperlight-wasm-runtime binary is expected to be in the build/{config} directory.
use std::fs::OpenOptions;
use std::io::Write;
@@ -167,8 +167,12 @@ fn build_wasm_runtime() -> PathBuf {
cmd.status()
.unwrap_or_else(|e| panic!("could not run cargo build hyperlight-wasm-runtime: {e:?}"));
+ let target_arch = format!(
+ "{}-hyperlight-none",
+ std::env::var("CARGO_CFG_TARGET_ARCH").unwrap()
+ );
let resource = target_dir
- .join("x86_64-hyperlight-none")
+ .join(target_arch)
.join(profile)
.join("hyperlight-wasm-runtime");
diff --git a/src/hyperlight_wasm/examples/tracing-otlp/main.rs b/src/hyperlight_wasm/examples/tracing-otlp/main.rs
index 805738e4..be8280bc 100644
--- a/src/hyperlight_wasm/examples/tracing-otlp/main.rs
+++ b/src/hyperlight_wasm/examples/tracing-otlp/main.rs
@@ -26,7 +26,7 @@ limitations under the License.
//! Prerequisites:
//! - An OTLP-compatible tracing backend (e.g., OpenTelemetry Collector, Jaeger,
//! Zipkin) running and accessible at `http://localhost:4318/v1/traces`.
-//! - The `rust_wasm_samples.aot` Wasm module available in the expected path (x64//).
+//! - The `rust_wasm_samples.aot` Wasm module available in the expected path (build//).
//! - The `trace_guest` feature enabled in the `hyperlight-wasm` crate.
//!
//! ```sh
diff --git a/src/hyperlight_wasm/scripts/build-wasm-examples.bat b/src/hyperlight_wasm/scripts/build-wasm-examples.bat
index 5170f8f5..7f7081ca 100644
--- a/src/hyperlight_wasm/scripts/build-wasm-examples.bat
+++ b/src/hyperlight_wasm/scripts/build-wasm-examples.bat
@@ -1,6 +1,6 @@
@echo off
pushd %~dp0\..\..\tests\c_guests\wasmsamples
-call :NORMALIZEPATH "..\..\..\..\x64\%1"
+call :NORMALIZEPATH "..\..\..\..\build\%1"
echo "%ABSPATH%"
call compile-wasm.bat "." "%ABSPATH%"
popd
diff --git a/src/hyperlight_wasm/scripts/build-wasm-examples.sh b/src/hyperlight_wasm/scripts/build-wasm-examples.sh
index 150644b9..9f1f94fc 100755
--- a/src/hyperlight_wasm/scripts/build-wasm-examples.sh
+++ b/src/hyperlight_wasm/scripts/build-wasm-examples.sh
@@ -5,7 +5,7 @@ set -o nounset
set -o pipefail
pushd "$(dirname "${BASH_SOURCE[0]}")/../../tests/c_guests/wasmsamples"
-OUTPUT_DIR="../../../../x64/${1:-"debug"}"
+OUTPUT_DIR="../../../../build/${1:-"debug"}"
BUILD_TYPE="${1:-"debug"}"
FEATURES="${2:-""}"
mkdir -p ${OUTPUT_DIR}
@@ -36,7 +36,12 @@ else
AOT_VERSION_FLAGS=""
fi
-if [ -f "/.dockerenv" ] || grep -q docker /proc/1/cgroup; then
+if [[ "${CI:-}" == "true" && "${RUNNER_ARCH:-}" == "ARM64" && -z "${CI_BUILD_WASM_MODULES:-}" ]]; then
+ # ARM64 gh runners do not have docker installed on the test
+ # runners, but will have already downloaded the built examples
+ # artifact from the builder job
+ echo "Running in GH Actions on ARM64, so not re-building examples"
+elif [ -f "/.dockerenv" ] || grep -q docker /proc/1/cgroup; then
# running in a container so use the installed wasi-sdk as the devcontainer has this installed
for FILENAME in $(find . -name '*.c' -not -path './components/*')
do
@@ -68,13 +73,16 @@ if [ -f "/.dockerenv" ] || grep -q docker /proc/1/cgroup; then
cargo run ${AOT_FEATURES} -p hyperlight-wasm-aot compile ${AOT_DEBUG_FLAGS} ${AOT_VERSION_FLAGS} --component ${OUTPUT_DIR}/${COMPONENT_NAME}-p2.wasm ${OUTPUT_DIR}/${COMPONENT_NAME}.aot
done
-else
+else
# not running in a container so use the docker image to build the wasm files
echo Building docker image that has Wasm sdk. Should be quick if preivoulsy built and no changes to dockerfile.
echo This will take a while if it is the first time you are building the docker image.
echo Log in ${OUTPUT_DIR}/dockerbuild.log
- docker pull ghcr.io/hyperlight-dev/wasm-clang-builder:latest
+ arch="$(uname -m)"
+ if [[ "$arch" == "x86_64" ]]; then
+ docker pull ghcr.io/hyperlight-dev/wasm-clang-builder:latest
+ fi
docker build --build-arg GCC_VERSION=12 --build-arg WASI_SDK_VERSION_FULL=25.0 --cache-from ghcr.io/hyperlight-dev/wasm-clang-builder:latest -t wasm-clang-builder:latest . 2> ${OUTPUT_DIR}/dockerbuild.log
diff --git a/src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs b/src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs
index 4ead108a..324f89fc 100644
--- a/src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs
+++ b/src/hyperlight_wasm/src/sandbox/wasm_sandbox.rs
@@ -696,7 +696,7 @@ mod tests {
.expect("Failed to get CARGO_MANIFEST_DIR or RUST_DIR_FOR_DEBUGGING_TESTS env var")
});
- let relative_path = "../../x64";
+ let relative_path = "../../build";
let filename_path = Path::new(&proj_dir)
.join(relative_path)
diff --git a/src/hyperlight_wasm_aot/src/main.rs b/src/hyperlight_wasm_aot/src/main.rs
index cb0ac8f9..0b39d404 100644
--- a/src/hyperlight_wasm_aot/src/main.rs
+++ b/src/hyperlight_wasm_aot/src/main.rs
@@ -27,6 +27,7 @@ use wasmtime::{Config, Engine, Module, OptLevel, Precompiled};
#[derive(Debug)]
enum SupportedTarget {
X86_64UnknownNone,
+ AArch64UnknownNone,
WasmtimePulley64,
}
@@ -34,6 +35,7 @@ impl Display for SupportedTarget {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SupportedTarget::X86_64UnknownNone => write!(f, "x86_64-unknown-none"),
+ SupportedTarget::AArch64UnknownNone => write!(f, "aarch64-unknown-none"),
SupportedTarget::WasmtimePulley64 => write!(f, "pulley64"),
}
}
@@ -112,7 +114,10 @@ fn precompile_bytes_lts(
if pulley {
config.target("pulley64").unwrap();
} else {
+ #[cfg(target_arch = "x86_64")]
config.target("x86_64-unknown-none").unwrap();
+ #[cfg(target_arch = "aarch64")]
+ config.target("aarch64-unknown-none").unwrap();
}
if debug {
config.debug_info(true);
@@ -133,7 +138,10 @@ fn precompile_bytes_lts(
/// Detect and deserialize using the LTS wasmtime version
fn detect_and_deserialize_lts(bytes: &[u8], debug: bool, file: &str) {
let mut config = wasmtime_lts::Config::new();
+ #[cfg(target_arch = "x86_64")]
config.target("x86_64-unknown-none").unwrap();
+ #[cfg(target_arch = "aarch64")]
+ config.target("aarch64-unknown-none").unwrap();
if debug {
config.debug_info(true);
config.cranelift_opt_level(wasmtime_lts::OptLevel::None);
@@ -189,7 +197,11 @@ fn main() {
let target = if pulley {
SupportedTarget::WasmtimePulley64
} else {
- SupportedTarget::X86_64UnknownNone
+ #[cfg(target_arch = "x86_64")]
+ let target = SupportedTarget::X86_64UnknownNone;
+ #[cfg(target_arch = "aarch64")]
+ let target = SupportedTarget::AArch64UnknownNone;
+ target
};
if debug {
println!(
@@ -216,7 +228,14 @@ fn main() {
let target_name = if pulley {
"pulley64"
} else {
- "x86_64-unknown-none"
+ #[cfg(target_arch = "x86_64")]
+ {
+ "x86_64-unknown-none"
+ }
+ #[cfg(target_arch = "aarch64")]
+ {
+ "aarch64-unknown-none"
+ }
};
if debug {
println!(
@@ -356,6 +375,9 @@ fn get_config(debug: bool, minimal: bool, target: &SupportedTarget) -> Config {
// See https://github.com/bytecodealliance/wasmtime/pull/11553
unsafe { config.x86_float_abi_ok(true) };
}
+ SupportedTarget::AArch64UnknownNone => {
+ config.target("aarch64-unknown-none").unwrap();
+ }
SupportedTarget::WasmtimePulley64 => {
config.target("pulley64").unwrap();
}
@@ -390,9 +412,7 @@ fn get_aot_target(bytes: &[u8]) -> Result {
if let Ok(elf) = ElfFile64::::parse(bytes) {
match elf.architecture() {
Architecture::X86_64 => Ok(SupportedTarget::X86_64UnknownNone),
- Architecture::Aarch64 => {
- Err("Unsupported architecture Aarch64 in AOT compiled file".to_string())
- }
+ Architecture::Aarch64 => Ok(SupportedTarget::AArch64UnknownNone),
Architecture::S390x => {
Err("Unsupported architecture S390x in AOT compiled file".to_string())
}
diff --git a/src/hyperlight_wasm_runtime/src/component.rs b/src/hyperlight_wasm_runtime/src/component.rs
index 3e871445..d5efe84e 100644
--- a/src/hyperlight_wasm_runtime/src/component.rs
+++ b/src/hyperlight_wasm_runtime/src/component.rs
@@ -108,8 +108,6 @@ fn load_wasm_module_phys(function_call: FunctionCall) -> Result {
#[no_mangle]
#[instrument(skip_all, level = "Info")]
pub extern "C" fn hyperlight_main() {
- platform::register_page_fault_handler();
-
let mut config = Config::new();
// Enable x86_float_abi_ok only for the latest Wasmtime native x86 target.
// Safety:
diff --git a/src/hyperlight_wasm_runtime/src/module.rs b/src/hyperlight_wasm_runtime/src/module.rs
index c28fae78..331eecf7 100644
--- a/src/hyperlight_wasm_runtime/src/module.rs
+++ b/src/hyperlight_wasm_runtime/src/module.rs
@@ -248,8 +248,6 @@ fn load_wasm_module_phys(function_call: FunctionCall) -> Result {
#[no_mangle]
#[instrument(skip_all, level = "Info")]
pub extern "C" fn hyperlight_main() {
- platform::register_page_fault_handler();
-
register_function(GuestFunctionDefinition::new(
"PrintOutput".to_string(),
vec![ParameterType::String],
diff --git a/src/hyperlight_wasm_runtime/src/platform.rs b/src/hyperlight_wasm_runtime/src/platform.rs
index 74f3ea90..60d32392 100644
--- a/src/hyperlight_wasm_runtime/src/platform.rs
+++ b/src/hyperlight_wasm_runtime/src/platform.rs
@@ -19,87 +19,82 @@ use core::ptr::NonNull;
use core::sync::atomic::{AtomicPtr, AtomicU64, Ordering};
use hyperlight_common::vmem;
-#[allow(deprecated)]
-use hyperlight_guest_bin::exception::arch;
-use hyperlight_guest_bin::paging;
+use hyperlight_guest_bin::{exception, paging};
+
+// Wasmtime Embedding Interface
+
+const WASMTIME_PROT_READ: u32 = 1 << 0;
+const WASMTIME_PROT_WRITE: u32 = 1 << 1;
+const WASMTIME_PROT_EXEC: u32 = 1 << 2;
+
+#[allow(non_camel_case_types)] // we didn't choose the name!
+type wasmtime_trap_handler_t =
+ extern "C" fn(ip: usize, fp: usize, has_faulting_addr: bool, faulting_addr: usize);
+static WASMTIME_REQUESTED_TRAP_HANDLER: spin::Mutex