diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 482f648..5c941a1 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -186,7 +186,7 @@ jobs: times=() for i in $(seq 1 15); do ms=$( { /usr/bin/time -f "%e" pyhl run -c "print(42)" > /dev/null; } 2>&1 ) - ms_int=$(echo "$ms * 1000" | bc | cut -d. -f1) + ms_int=$(echo "$ms * 1000" | tr -d '\r' | bc | cut -d. -f1) times+=($ms_int) echo " run $i: ${ms_int}ms" done @@ -223,7 +223,7 @@ jobs: times=() for i in $(seq 1 10); do ms=$( { /usr/bin/time -f "%e" pyhl run /tmp/pandas_bench.py > /dev/null; } 2>&1 ) - ms_int=$(echo "$ms * 1000" | bc | cut -d. -f1) + ms_int=$(echo "$ms * 1000" | tr -d '\r' | bc | cut -d. -f1) times+=($ms_int) echo " run $i: ${ms_int}ms" done diff --git a/.github/workflows/test-examples.yml b/.github/workflows/test-examples.yml index d372ee3..42deb90 100644 --- a/.github/workflows/test-examples.yml +++ b/.github/workflows/test-examples.yml @@ -216,7 +216,18 @@ jobs: - example: python-agent-driver args: "" expect: "hello from driver" - driver: pydriver-run + driver: pyhl + pyhl_code: "print('hello from driver')" + - example: python-agent-driver + args: "" + expect: "hello from hyperlight guest" + driver: pyhl + pyhl_script: demo_busybox.py + - example: python-agent-driver + args: "--net" + expect: "imported six" + driver: pyhl + pyhl_script: demo_pip_install.py - example: powershell args: "-- -NoProfile -File /scripts/hello.ps1" expect: "Hello, World! From PowerShell on Hyperlight" @@ -281,8 +292,9 @@ jobs: if: steps.kvm_check.outputs.available == 'true' run: | cd host - cargo build --release --features wasm-host-fns --bin hyperlight-unikraft --bin multifn-test --bin pydriver-run + cargo build --release --features wasm-host-fns --bin hyperlight-unikraft --bin multifn-test --bin pyhl sudo cp target/release/hyperlight-unikraft /usr/local/bin/ + sudo cp target/release/pyhl /usr/local/bin/ - name: Build echo Wasm host function if: steps.kvm_check.outputs.available == 'true' && matrix.needs_echo_tool == true @@ -322,9 +334,10 @@ jobs: kraft-hyperlight --no-prompt build --plat hyperlight --arch x86_64 fi - - name: Prepare pydriver-run script (python-agent-driver only) - if: steps.kvm_check.outputs.available == 'true' && matrix.driver == 'pydriver-run' - run: echo 'print("hello from driver")' > /tmp/tiny.py + - name: pyhl setup (python-agent-driver only) + if: steps.kvm_check.outputs.available == 'true' && matrix.driver == 'pyhl' + working-directory: examples/${{ matrix.example }} + run: pyhl setup --from . --force - name: Run and check output if: steps.kvm_check.outputs.available == 'true' @@ -401,8 +414,17 @@ jobs: multifn-test) cmd=(timeout 60 /home/runner/work/hyperlight-unikraft/hyperlight-unikraft/host/target/release/multifn-test "$kernel" "$cpio") ;; - pydriver-run) - cmd=(timeout 120 /home/runner/work/hyperlight-unikraft/hyperlight-unikraft/host/target/release/pydriver-run "$kernel" "$cpio" /tmp/tiny.py) + pyhl) + pyhl_args=() + if [ -n "${{ matrix.pyhl_script }}" ]; then + pyhl_args+=(examples/${{ matrix.example }}/${{ matrix.pyhl_script }}) + elif [ -n "${{ matrix.pyhl_code }}" ]; then + pyhl_args+=(-c "${{ matrix.pyhl_code }}") + fi + if echo "${{ matrix.args }}" | grep -q "\-\-net"; then + pyhl_args+=(--net) + fi + cmd=(timeout 300 pyhl run -v "${pyhl_args[@]}") ;; *) mem_args="" @@ -606,7 +628,18 @@ jobs: - example: python-agent-driver args: "" expect: "hello from driver" - driver: pydriver-run + driver: pyhl + pyhl_code: "print('hello from driver')" + - example: python-agent-driver + args: "" + expect: "hello from hyperlight guest" + driver: pyhl + pyhl_script: demo_busybox.py + - example: python-agent-driver + args: "--net" + expect: "imported six" + driver: pyhl + pyhl_script: demo_pip_install.py - example: powershell args: "-- -NoProfile -File /scripts/hello.ps1" expect: "Hello, World! From PowerShell on Hyperlight" @@ -645,10 +678,9 @@ jobs: shell: pwsh run: | cd host - cargo build --release --features wasm-host-fns --bin hyperlight-unikraft --bin multifn-test --bin pydriver-run --bin pyhl + cargo build --release --features wasm-host-fns --bin hyperlight-unikraft --bin multifn-test --bin pyhl Copy-Item target\release\hyperlight-unikraft.exe $env:USERPROFILE\.cargo\bin\ -Force Copy-Item target\release\multifn-test.exe $env:USERPROFILE\.cargo\bin\ -Force - Copy-Item target\release\pydriver-run.exe $env:USERPROFILE\.cargo\bin\ -Force Copy-Item target\release\pyhl.exe $env:USERPROFILE\.cargo\bin\ -Force - name: Build echo Wasm host function @@ -664,6 +696,15 @@ jobs: name: windows-image-${{ matrix.example }} path: image + - name: pyhl setup (python-agent-driver only) + if: matrix.driver == 'pyhl' + shell: pwsh + run: | + New-Item -ItemType Directory -Force -Path src-dir/.unikraft/build | Out-Null + Copy-Item image/kernel src-dir/.unikraft/build/pyhl-kernel_hyperlight-x86_64 + Copy-Item image/initrd.cpio src-dir/pyhl-initrd.cpio + pyhl setup --from src-dir --force + - name: Run and check output shell: pwsh run: | @@ -758,10 +799,20 @@ jobs: $out = & multifn-test $kernel $cpio 2>&1 $rc = $LASTEXITCODE } - 'pydriver-run' { - "print('hello from driver')" | Out-File -Encoding ascii tiny.py - $tiny = (Resolve-Path "tiny.py").Path - $out = & pydriver-run $kernel $cpio $tiny 2>&1 + 'pyhl' { + $pyhlArgs = @('run', '-v') + $pyhlScript = "${{ matrix.pyhl_script }}" + $pyhlCode = "${{ matrix.pyhl_code }}" + if ($pyhlScript -ne '') { + Copy-Item "examples/${{ matrix.example }}/$pyhlScript" -Destination tiny.py + $pyhlArgs += (Resolve-Path "tiny.py").Path + } elseif ($pyhlCode -ne '') { + $pyhlArgs += @('-c', $pyhlCode) + } + if ($runArgs -match '--net') { + $pyhlArgs += '--net' + } + $out = & pyhl @pyhlArgs 2>&1 $rc = $LASTEXITCODE } default { diff --git a/examples/dotnet-http/kraft.yaml b/examples/dotnet-http/kraft.yaml index 37c6ed0..977c820 100644 --- a/examples/dotnet-http/kraft.yaml +++ b/examples/dotnet-http/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: dotnet-http-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -90,8 +90,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/dotnet-nativeaot/kraft.yaml b/examples/dotnet-nativeaot/kraft.yaml index f5c2b2d..a7e2a30 100644 --- a/examples/dotnet-nativeaot/kraft.yaml +++ b/examples/dotnet-nativeaot/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: dotnet-nativeaot-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: CONFIG_PLAT_HYPERLIGHT: 'y' CONFIG_PAGING: 'n' @@ -56,8 +56,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/dotnet/kraft.yaml b/examples/dotnet/kraft.yaml index b2b0a3b..9d7e87b 100644 --- a/examples/dotnet/kraft.yaml +++ b/examples/dotnet/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: dotnet-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -78,8 +78,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/go-http/kraft.yaml b/examples/go-http/kraft.yaml index d06b787..73bb118 100644 --- a/examples/go-http/kraft.yaml +++ b/examples/go-http/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: go-http-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -79,8 +79,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/go/kraft.yaml b/examples/go/kraft.yaml index 547d6d7..046daec 100644 --- a/examples/go/kraft.yaml +++ b/examples/go/kraft.yaml @@ -3,8 +3,8 @@ specification: '0.6' name: go-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -64,8 +64,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/helloworld-c/kraft.yaml b/examples/helloworld-c/kraft.yaml index 36e45f2..613ba6c 100644 --- a/examples/helloworld-c/kraft.yaml +++ b/examples/helloworld-c/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: helloworld-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: CONFIG_PLAT_HYPERLIGHT: 'y' CONFIG_PAGING: 'n' @@ -55,8 +55,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/hostfs-posix-c/kraft.yaml b/examples/hostfs-posix-c/kraft.yaml index d2f937f..80686e9 100644 --- a/examples/hostfs-posix-c/kraft.yaml +++ b/examples/hostfs-posix-c/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: hostfs-posix-c-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -71,8 +71,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/hostfs-posix-py/kraft.yaml b/examples/hostfs-posix-py/kraft.yaml index ec17d14..fbc0e8a 100644 --- a/examples/hostfs-posix-py/kraft.yaml +++ b/examples/hostfs-posix-py/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: hostfs-posix-py-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -76,8 +76,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/multifn-c/kraft.yaml b/examples/multifn-c/kraft.yaml index cc98096..c62dcad 100644 --- a/examples/multifn-c/kraft.yaml +++ b/examples/multifn-c/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: multifn-c-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: CONFIG_PLAT_HYPERLIGHT: 'y' CONFIG_PAGING: 'n' @@ -49,8 +49,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/networking-py/kraft.yaml b/examples/networking-py/kraft.yaml index 67531a4..d44912a 100644 --- a/examples/networking-py/kraft.yaml +++ b/examples/networking-py/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: networking-py-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -72,8 +72,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/nodejs/kraft.yaml b/examples/nodejs/kraft.yaml index 4639e1a..e3f6391 100644 --- a/examples/nodejs/kraft.yaml +++ b/examples/nodejs/kraft.yaml @@ -3,8 +3,8 @@ specification: '0.6' name: nodejs-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -74,8 +74,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/powershell/kraft.yaml b/examples/powershell/kraft.yaml index 8d3bcc9..806d44d 100644 --- a/examples/powershell/kraft.yaml +++ b/examples/powershell/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: powershell-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -86,8 +86,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/python-agent-driver/Dockerfile b/examples/python-agent-driver/Dockerfile index 82f8076..ece2ce8 100644 --- a/examples/python-agent-driver/Dockerfile +++ b/examples/python-agent-driver/Dockerfile @@ -48,6 +48,17 @@ RUN set -eux; \ find /deps -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true; \ find /deps -type f -name '*.pyc' -delete 2>/dev/null || true; \ find /deps -name '*.so*' -exec strip --strip-unneeded {} + 2>/dev/null || true +# Patch pip's user_agent() — the original probes platform/distro/libc/ssl +# which triggers buddy allocator corruption in unikraft's memory manager. +RUN python3 -c "\ +import re, pathlib, sys; \ +p = pathlib.Path('/usr/local/lib/python3.12/site-packages/pip/_internal/network/session.py'); \ +src = p.read_text(); \ +patched = re.sub(r'(def user_agent\(\)[^:]*:).*?(\n(?:def |class ))', \ + r'\1\n return \"pip/hyperlight\"\n\n\2', src, count=1, flags=re.DOTALL); \ +assert patched != src, 'pip user_agent() regex did not match — pip version changed?'; \ +p.write_text(patched)" && \ + python3 -c "from pip._internal.network.session import user_agent; assert user_agent() == 'pip/hyperlight'" # Stage 2: build hl_pydriver against the SAME Python 3.12-from-source # that produces local-python-base, so the glibc/libpython3.12.so ABI @@ -70,11 +81,47 @@ FROM ${BASE} AS rootfs COPY --from=deps /deps /usr/local/lib/python3.12/site-packages COPY --from=driver-build /src/hl_pydriver /bin/hl_pydriver COPY pydoc_stub.py /usr/local/lib/python3.12/pydoc.py +# pip for in-guest package installation (vfork+execve subprocess) +COPY --from=deps /usr/local/lib/python3.12/site-packages/pip /usr/local/lib/python3.12/site-packages/pip +COPY --from=deps /usr/local/lib/python3.12/ensurepip /usr/local/lib/python3.12/ensurepip +# stdlib modules needed by pip but missing from python-base +COPY --from=deps /usr/local/lib/python3.12/xmlrpc /usr/local/lib/python3.12/xmlrpc +COPY --from=deps /usr/local/lib/python3.12/zipapp.py /usr/local/lib/python3.12/zipapp.py +# DNS-over-TCP resolver and pip target path (vfork subprocess support) +COPY rootfs/usr/local/lib/python3.12/sitecustomize.py /usr/local/lib/python3.12/sitecustomize.py +COPY rootfs/etc/pip.conf /etc/pip.conf + +# Stage 3b: build static PIE busybox (elfloader only supports ET_DYN). +FROM debian:bookworm-slim AS utils-build +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc libc6-dev make wget bzip2 ca-certificates && \ + rm -rf /var/lib/apt/lists/* +RUN wget -q https://busybox.net/downloads/busybox-1.36.1.tar.bz2 && \ + tar xf busybox-1.36.1.tar.bz2 && cd busybox-1.36.1 && \ + make defconfig && \ + sed -i 's/CONFIG_TC=y/# CONFIG_TC is not set/' .config && \ + sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config && \ + sed -i 's|CONFIG_EXTRA_CFLAGS=""|CONFIG_EXTRA_CFLAGS="-fPIE -fPIC"|' .config && \ + make -j$(nproc) && \ + gcc -fPIE -fPIC -static-pie -o /busybox \ + -Wl,--sort-common -Wl,--sort-section -Wl,alignment \ + -Wl,--start-group \ + applets/built-in.o \ + $(find . -name 'lib.a' -path './*/lib.a' | sort) \ + -Wl,--end-group \ + -lm -lresolv && \ + strip /busybox # Stage 4: pack CPIO. FROM alpine:3.20 AS cpio RUN apk add --no-cache cpio findutils ca-certificates COPY --from=rootfs / /rootfs/ +COPY --from=utils-build /busybox /rootfs/bin/busybox +RUN cd /rootfs && for cmd in sh cat ls cp mv rm mkdir rmdir ln head tail wc \ + grep sed awk sort uniq tr cut tee xargs find test basename dirname \ + env which id whoami uname hostname date sleep echo true; do \ + ln -sf busybox bin/$cmd; \ + done # DNS configuration for glibc's getaddrinfo RUN mkdir -p /rootfs/etc && \ diff --git a/examples/python-agent-driver/demo_busybox.py b/examples/python-agent-driver/demo_busybox.py new file mode 100644 index 0000000..7bdebbf --- /dev/null +++ b/examples/python-agent-driver/demo_busybox.py @@ -0,0 +1,22 @@ +import subprocess + +cmds = [ + (["echo", "hello from hyperlight guest"], None), + (["uname", "-a"], None), + (["ls", "/bin"], None), + (["grep", "nameserver", "/etc/resolv.conf"], None), + (["find", "/etc", "-name", "*.conf"], None), + (["wc", "-l", "/etc/resolv.conf"], None), + (["sh", "-c", "echo hello from sh"], None), +] + +for cmd, stdin in cmds: + label = " ".join(cmd) + print(f"\n$ {label}") + r = subprocess.run(cmd, capture_output=True, text=True, input=stdin) + if r.stdout: + print(r.stdout.rstrip()) + if r.stderr: + print(f"stderr: {r.stderr.rstrip()}") + if r.returncode != 0: + print(f"exit code: {r.returncode}") diff --git a/examples/python-agent-driver/demo_pip_install.py b/examples/python-agent-driver/demo_pip_install.py new file mode 100644 index 0000000..ac454d2 --- /dev/null +++ b/examples/python-agent-driver/demo_pip_install.py @@ -0,0 +1,13 @@ +import subprocess, sys + +result = subprocess.run( + [sys.executable, "-m", "pip", "install", "six"], + capture_output=True, text=True, +) +print(result.stdout) +if result.returncode != 0: + print(result.stderr) + sys.exit(result.returncode) + +import six +print(f"Installed and imported six {six.__version__}") diff --git a/examples/python-agent-driver/hl_pydriver.c b/examples/python-agent-driver/hl_pydriver.c index 16c8266..2c21d73 100644 --- a/examples/python-agent-driver/hl_pydriver.c +++ b/examples/python-agent-driver/hl_pydriver.c @@ -199,6 +199,12 @@ static int run_code_with_exceptions(const char *code) return 1; } +static const char warmup_prefix[] = + "import subprocess as __sp\n" + "__sp.run(['true'])\n" + "__sp.run(['true'])\n" + "del __sp\n"; + static void py_run_user_code(const uint8_t *fc, size_t fc_len) { if (g_py_fsbase) @@ -209,20 +215,22 @@ static void py_run_user_code(const uint8_t *fc, size_t fc_len) if (!code) return; - char stack_buf[4096]; + size_t prefix_len = sizeof(warmup_prefix) - 1; + size_t total = prefix_len + code_len; + char stack_buf[8192]; char *buf; - if (code_len < sizeof(stack_buf)) { - memcpy(stack_buf, code, code_len); - stack_buf[code_len] = '\0'; + if (total < sizeof(stack_buf)) { buf = stack_buf; } else { - buf = malloc(code_len + 1); + buf = malloc(total + 1); if (!buf) return; - memcpy(buf, code, code_len); - buf[code_len] = '\0'; } + memcpy(buf, warmup_prefix, prefix_len); + memcpy(buf + prefix_len, code, code_len); + buf[total] = '\0'; + int exit_code = run_code_with_exceptions(buf); if (buf != stack_buf) @@ -344,14 +352,6 @@ int main(int argc, char **argv, char **envp) fflush(stdout); fflush(stderr); - /* Hand-rolled exit_group via inline syscall: skips glibc's - * exit() atexit chain AND any TLS state glibc's syscall() - * wrapper might touch (seen the latter corrupt Python's TLS - * between first-call halt and second-call re-entry in - * testing). The kernel's exit_group handler on - * Unikraft-Hyperlight halts the VM cleanly — same end effect - * as a normal return, just without the destructive cleanup. - */ register long rax __asm__("rax") = 231; /* SYS_exit_group */ register long rdi __asm__("rdi") = 0; __asm__ volatile("syscall" : : "r"(rax), "r"(rdi) diff --git a/examples/python-agent-driver/kraft.yaml b/examples/python-agent-driver/kraft.yaml index 425b327..80c8b80 100644 --- a/examples/python-agent-driver/kraft.yaml +++ b/examples/python-agent-driver/kraft.yaml @@ -2,14 +2,15 @@ specification: '0.6' name: python-agent-driver-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: CONFIG_PLAT_HYPERLIGHT: 'y' CONFIG_PAGING: 'n' CONFIG_LIBUKVMEM: 'n' CONFIG_LIBUKINTCTLR_HYPERLIGHT: 'y' CONFIG_HYPERLIGHT_MAX_GUEST_LOG_LEVEL: 4 + CONFIG_LIBSYSCALL_SHIM_STRACE: 'n' CONFIG_LIBUKPRINT_KLVL_CRIT: 'y' CONFIG_LIBUKPRINT_PRINT_TIME: 'n' @@ -70,21 +71,25 @@ unikraft: CONFIG_LIBPOSIX_PROCESS_ARCH_PRCTL: 'y' CONFIG_LIBPOSIX_PROCESS_MULTIPROCESS: 'y' - CONFIG_LIBPOSIX_PROCESS_EXECVE: 'y' CONFIG_LIBPOSIX_PROCESS_SIGNAL: 'y' + CONFIG_LIBPOSIX_PROCESS_EXECVE: 'y' CONFIG_LIBUKBINFMT: 'y' - CONFIG_APPELFLOADER_MULTIPROCESS: 'y' CONFIG_APPELFLOADER_ELF_BINFMT: 'y' CONFIG_LIBCONTEXT: 'y' CONFIG_LIBCONTEXT_CLEAR_TBSS: 'y' + CONFIG_APPELFLOADER_MULTIPROCESS: 'y' + CONFIG_LIBPOSIX_FDTAB_MULTITAB: 'n' + CONFIG_STACK_SIZE_PAGE_ORDER: 10 + CONFIG_LIBUKDEBUG_ENABLE_ASSERT: 'n' + libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/python-agent/kraft.yaml b/examples/python-agent/kraft.yaml index d627dc3..dccb200 100644 --- a/examples/python-agent/kraft.yaml +++ b/examples/python-agent/kraft.yaml @@ -2,8 +2,8 @@ specification: '0.6' name: python-agent-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -88,8 +88,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/python-tools/kraft.yaml b/examples/python-tools/kraft.yaml index 53de59f..d969197 100644 --- a/examples/python-tools/kraft.yaml +++ b/examples/python-tools/kraft.yaml @@ -3,8 +3,8 @@ specification: '0.6' name: python-tools-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -66,8 +66,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/python/kraft.yaml b/examples/python/kraft.yaml index dba5357..f47b947 100644 --- a/examples/python/kraft.yaml +++ b/examples/python/kraft.yaml @@ -3,8 +3,8 @@ specification: '0.6' name: python-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -67,8 +67,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/rust/kraft.yaml b/examples/rust/kraft.yaml index 962a7e9..19411ac 100644 --- a/examples/rust/kraft.yaml +++ b/examples/rust/kraft.yaml @@ -3,8 +3,8 @@ specification: '0.6' name: rust-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -62,8 +62,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/examples/shell/kraft.yaml b/examples/shell/kraft.yaml index 242745b..fba267e 100644 --- a/examples/shell/kraft.yaml +++ b/examples/shell/kraft.yaml @@ -3,8 +3,8 @@ specification: '0.6' name: shell-hyperlight unikraft: - source: https://github.com/unikraft/unikraft.git - version: plat-hyperlight + source: https://github.com/danbugs/unikraft.git + version: proto/vfork kconfig: # Platform CONFIG_PLAT_HYPERLIGHT: 'y' @@ -65,8 +65,8 @@ unikraft: libraries: app-elfloader: - source: https://github.com/unikraft/app-elfloader.git - version: plat-hyperlight + source: https://github.com/danbugs/app-elfloader.git + version: proto/vfork libelf: source: https://github.com/unikraft/lib-libelf.git version: staging diff --git a/host/Cargo.toml b/host/Cargo.toml index 8c04c31..97b5021 100644 --- a/host/Cargo.toml +++ b/host/Cargo.toml @@ -23,10 +23,6 @@ path = "src/main.rs" name = "multifn-test" path = "src/bin/multifn_test.rs" -[[bin]] -name = "pydriver-run" -path = "src/bin/pydriver_run.rs" - [[bin]] name = "pyhl" path = "src/bin/pyhl.rs" diff --git a/host/src/bin/pydriver_run.rs b/host/src/bin/pydriver_run.rs deleted file mode 100644 index 448f83c..0000000 --- a/host/src/bin/pydriver_run.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! pydriver-run — run a Python script through hl_pydriver. -//! -//! Boots the sandbox once, calls "run" with the script's contents. -//! First call pays the Py_Initialize + warm-up import cost (~2 s); -//! the driver registers an FC-aware callback during that call, so -//! every subsequent call (via --repeat N or snapshot_now + loop) is -//! just the user's code + dispatch overhead. -//! -//! Usage: -//! pydriver-run [--repeat N] -//! -//! With --repeat, after the first (warmup + code) call we -//! `snapshot_now()` to capture the post-warmup state, then restore + -//! call_named for each remaining iteration so we can actually -//! *measure* the warm-path cost on runs 2..N. - -use anyhow::{anyhow, Result}; -use hyperlight_unikraft::Sandbox; -use std::path::PathBuf; -use std::time::Instant; - -fn main() -> Result<()> { - let mut args = std::env::args().skip(1); - let kernel = args - .next() - .ok_or_else(|| anyhow!("usage: pydriver-run