From 0523d3aa15d9954f358f78784a7a5e0fdb48bb30 Mon Sep 17 00:00:00 2001 From: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com> Date: Thu, 2 Apr 2026 14:04:34 -0700 Subject: [PATCH] Update README Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com> --- .gitignore | 1 + README.md | 325 +++++------------- docs/README.md | 1 + docs/getting-started.md | 155 +++++++++ .../how-to-build-a-hyperlight-guest-binary.md | 152 ++++++-- 5 files changed, 364 insertions(+), 270 deletions(-) create mode 100644 docs/getting-started.md diff --git a/.gitignore b/.gitignore index dbd55529f..3aae7b792 100644 --- a/.gitignore +++ b/.gitignore @@ -473,3 +473,4 @@ hyperlight_guest.h .gdbinit trace/* .gdbguest +.copilot-reviews/ diff --git a/README.md b/README.md index 9d88802c7..ade86b6d2 100644 --- a/README.md +++ b/README.md @@ -1,277 +1,124 @@

Hyperlight

hyperlight logo -

Hyperlight is a lightweight Virtual Machine Manager (VMM) designed to be embedded within applications. It enables safe execution of untrusted code within micro virtual machines with very low latency and minimal overhead.
We are a Cloud Native Computing Foundation sandbox project.

+

+ A lightweight VMM for running untrusted code in micro VMs with minimal overhead.
+ A Cloud Native Computing Foundation sandbox project. +

-> Note: Hyperlight is a nascent project with an evolving API and no guaranteed support. Assistance is provided on a -> best-effort basis by the developers. +> **Status:** Hyperlight is pre-1.0. The API may change between releases, and upgrading will sometimes require code changes. ---- - -## Overview - -Hyperlight is a library for creating _micro virtual machines_ — or _sandboxes_ — specifically optimized for securely -running untrusted code with minimal impact. It supports both Windows and Linux, -utilizing [Windows Hypervisor Platform](https://docs.microsoft.com/en-us/virtualization/api/#windows-hypervisor-platform) -on Windows, and either Microsoft Hypervisor (mshv) or [KVM](https://linux-kvm.org/page/Main_Page) on Linux. - -These micro VMs operate without a kernel or operating system, keeping overhead low. Instead, guests are built -specifically for Hyperlight using the Hyperlight Guest library, which provides a controlled set of APIs that facilitate -interaction between host and guest: +Hyperlight lets you safely run untrusted code inside hypervisor-isolated micro VMs that spin up in milliseconds, with guest function calls completing in microseconds. You embed it as a library in your Rust application, hand it a guest binary, and call functions across the VM boundary as naturally as calling a local function. To minimize startup time and memory footprint, there's no guest kernel or OS. Guests are purpose-built using the Hyperlight guest library. -- The host can call functions implemented and exposed by the guest (known as _guest functions_). -- Once running, the guest can call functions implemented and exposed by the host (known as _host functions_). +- Supports [KVM](https://linux-kvm.org/page/Main_Page), [MSHV](https://github.com/rust-vmm/mshv), and [Windows Hypervisor Platform](https://docs.microsoft.com/en-us/virtualization/api/#windows-hypervisor-platform) +- No kernel or OS in the VM. Guests are regular ELF binaries written in `no_std` Rust or C +- Host and guest communicate through typed function calls +- Guests are sandboxed by default with no access to the host filesystem, network, etc. -By default, Hyperlight restricts guest access to a minimal API. The only _host function_ available by default allows the -guest to print messages, which are displayed on the host console or redirected to stdout, as configured. Hosts can -choose to expose additional host functions, expanding the guest’s capabilities as needed. +## Example -Below is an example demonstrating the use of the Hyperlight host library in Rust to execute a simple guest application. -It is followed by an example of a simple guest application using the Hyperlight guest library, also written in Rust. - -### Host +**Host** - create a sandbox, register a host function, and call into the guest: ```rust -use std::thread; - -use hyperlight_host::{MultiUseSandbox, UninitializedSandbox}; - -fn main() -> hyperlight_host::Result<()> { - // Create an uninitialized sandbox with a guest binary - let mut uninitialized_sandbox = UninitializedSandbox::new( - hyperlight_host::GuestBinary::FilePath("path/to/your/guest/binary".to_string()), - None // default configuration - )?; - - // Registering a host function makes it available to be called by the guest - uninitialized_sandbox.register("Sleep5Secs", || { - thread::sleep(std::time::Duration::from_secs(5)); - Ok(()) - })?; - // Note: This function is unused by the guest code below, it's just here for demonstration purposes - - // Initialize sandbox to be able to call host functions - let mut multi_use_sandbox: MultiUseSandbox = uninitialized_sandbox.evolve()?; - - // Call a function in the guest - let message = "Hello, World! I am executing inside of a VM :)\n".to_string(); - // in order to call a function it first must be defined in the guest and exposed so that - // the host can call it - multi_use_sandbox.call::( - "PrintOutput", - message, - )?; - - Ok(()) -} -``` +// Create an uninitialized sandbox by giving it the path to a guest binary. +// Allocates memory but does not yet run a VM. +let mut sandbox = UninitializedSandbox::new(GuestBinary::FilePath(guest_path), None)?; -### Guest +// Register a host function that the guest can call. In a real app this +// might query a database, read a config, or call an external API. +// By default, guests can only print to the host. +sandbox.register("GetWeekday", || Ok("Monday".to_string()))?; -First, create a `Cargo.toml` with the required dependencies: +// Initialize the sandbox. Starts the VM and runs guest setup code. +let mut sandbox: MultiUseSandbox = sandbox.evolve()?; -```toml -[package] -name = "my-hyperlight-guest" -version = "0.1.0" -edition = "2024" - -[dependencies] -hyperlight-guest = "0.12" -hyperlight-guest-bin = "0.12" -hyperlight-common = { version = "0.12", default-features = false } +// Call a function inside the VM +let greeting: String = sandbox.call("SayHello", "World".to_string())?; +println!("{greeting}"); // "Hello, World! Today is Monday." ``` -> **Important:** The `hyperlight-common` crate must have `default-features = false` to avoid pulling in -> the standard library, which conflicts with the `no_std` requirement for guests. +Guest state persists across calls. Use `snapshot()` and `restore()` to save and reset VM memory. This avoids recreating the VM while ensuring each call starts from a clean state. -Then, create `src/main.rs`: +**Guest** (Rust) - declare host functions and expose guest functions with simple macros. Guests can also be [written in C](./src/hyperlight_guest_capi). ```rust -#![no_std] -#![no_main] -extern crate alloc; -extern crate hyperlight_guest_bin; - -use alloc::vec::Vec; -use alloc::string::String; -use hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall; -use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode; - -use hyperlight_guest::bail; -use hyperlight_guest::error::Result; -use hyperlight_guest_bin::{guest_function, host_function}; - -#[host_function("HostPrint")] -fn host_print(message: String) -> Result; - -#[guest_function("PrintOutput")] -fn print_output(message: String) -> Result { - let result = host_print(message)?; - Ok(result) -} - -#[no_mangle] -pub extern "C" fn hyperlight_main() { - // any initialization code goes here -} +#[host_function("GetWeekday")] +fn get_weekday() -> Result; -#[no_mangle] -pub fn guest_dispatch_function(function_call: FunctionCall) -> Result> { - let function_name = function_call.function_name; - bail!(ErrorCode::GuestFunctionNotFound => "{function_name}"); +#[guest_function("SayHello")] +fn say_hello(name: String) -> Result { + let weekday = get_weekday()?; + Ok(format!("Hello, {name}! Today is {weekday}.")) } ``` -Build the guest using [cargo-hyperlight](https://github.com/hyperlight-dev/cargo-hyperlight): +To get started, see the [Getting Started](./docs/getting-started.md) guide. For more details on writing guests, see [How to build a Hyperlight guest binary](./docs/how-to-build-a-hyperlight-guest-binary.md). -```sh -cargo install --locked cargo-hyperlight -cargo hyperlight build -``` - -> **Note:** You must use `cargo hyperlight build` instead of the regular `cargo build` command. -> The `cargo-hyperlight` tool sets up the required custom target, sysroot, and compiler flags -> that are necessary for building Hyperlight guests. +## When to use Hyperlight -For additional examples of using the Hyperlight host Rust library, see -the [./src/hyperlight_host/examples](./src/hyperlight_host/examples) directory. +Hyperlight is a good fit when you need to: -For examples of guest applications, see the [./src/tests/c_guests](./src/tests/c_guests) directory for C guests and -the [./src/tests/rust_guests](./src/tests/rust_guests) directory for Rust guests. +- Run untrusted or third-party code with hypervisor-level isolation +- Create and tear down sandboxes in milliseconds +- Make guest function calls in microseconds +- Embed sandboxed execution directly in your application +- Build functions-as-a-service with hypervisor-level isolation +- Reuse sandboxes efficiently with snapshot and restore -> Note: Hyperlight guests can be written using the Hyperlight Rust or C Guest libraries. +Hyperlight is *not* designed for: -## Repository Structure +- General-purpose virtualization (use a full VMM instead) +- Running full-blown Linux guest workloads that need syscalls, networking, or filesystem access -- Hyperlight Host Libraries (i.e., the ones that create and manage the VMs) - - [src/hyperlight_host](./src/hyperlight_host) - This is the Rust Hyperlight host library. +## Getting started -- Hyperlight Guest Libraries (i.e., the ones to make it easier to create guests that run inside the VMs) - - [src/hyperlight_guest](./src/hyperlight_guest) - The core Rust library for Hyperlight guests. It provides only the essential building blocks for interacting with the host environment, including the VM exit mechanism (`outb`), abstractions for calling host functions and receiving return values, and the input/output stacks used for guest-host communication. - - [src/hyperlight_guest_bin](./src/hyperlight_guest_bin/) - An extension to the core Rust library for Hyperlight guests. It contains more opinionated components (e.g., panic handler, heap initialization, musl-specific imports, logging, and exception handling). - - [src/hyperlight_guest_capi](./src/hyperlight_guest_capi) - A C-compatible wrapper around `hyperlight_guest_bin`, exposing its core functionality for use in C programs and other languages via FFI. +See [docs/getting-started.md](./docs/getting-started.md) for detailed prerequisites and platform-specific setup for: +- **Running** Hyperlight +- **Building guests** -- Hyperlight Common (functionality used by both the host and the guest) - - [src/hyperlight_common](./src/hyperlight_common) - -- Test Guest Applications: - - [src/tests/rust_guests](./src/tests/rust_guests) - This directory contains three Hyperlight Guest programs written - in Rust, which are intended to be launched within partitions as "guests". - - [src/tests/c_guests](./src/tests/c_guests) - This directory contains two Hyperlight Guest programs written in C, - which are intended to be launched within partitions as "guests". - -- Tests: - - [src/hyperlight-testing](./src/hyperlight_testing) - Shared testing code for Hyperlight projects built in Rust. - -## Try it yourself! - -You can run Hyperlight on: - -- [Linux with KVM][kvm]. -- [Windows with Windows Hypervisor Platform (WHP).][whp] - Note that you need Windows 11 / Windows Server 2022 or later to use hyperlight, if you are running on earlier versions of Windows then you should consider using our devcontainer on [GitHub codespaces]((https://codespaces.new/hyperlight-dev/hyperlight)) or WSL2. -- Windows Subsystem for Linux 2 (see instructions [here](https://learn.microsoft.com/en-us/windows/wsl/install) for Windows client and [here](https://learn.microsoft.com/en-us/windows/wsl/install-on-server) for Windows Server) with KVM. -- Azure Linux with mshv (note that you need mshv to be installed to use Hyperlight) - -After having an environment with a hypervisor setup, running the example has the following pre-requisites: - -1. On Linux or WSL, you'll most likely need build essential. For Ubuntu, run `sudo apt install build-essential`. For - Azure Linux, run `sudo dnf install build-essential`. -2. [Rust](https://www.rust-lang.org/tools/install). Install toolchain v1.89 or later. -3. [just](https://github.com/casey/just). `cargo install just` On Windows you also need [pwsh](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.4). -4. [clang and LLVM](https://clang.llvm.org/get_started.html). - - On Ubuntu, run: - - ```sh - wget https://apt.llvm.org/llvm.sh - chmod +x ./llvm.sh - sudo ./llvm.sh 18 clang clang-tools-extra - sudo ln -s /usr/lib/llvm-18/bin/ld.lld /usr/bin/ld.lld - sudo ln -s /usr/lib/llvm-18/bin/clang /usr/bin/clang - ``` - - - On Windows, see [this](https://learn.microsoft.com/en-us/cpp/build/clang-support-msbuild?view=msvc-170). - - - On Azure Linux, run: - - ```sh - if ! command -v clang > /dev/null 2>&1; then - sudo dnf install clang -y - sudo dnf install clang-tools-extra -y - fi - ``` - -Then, we are ready to build and run the example: - -```sh -just build # build the Hyperlight library -just rg # build the rust test guest binaries -cargo run --example hello-world -``` - -If all worked as expected, you should see the following message in your console: - -```text -Hello, World! I am executing inside of a VM :) -``` - -If you get the error `Error: NoHypervisorFound` and KVM or mshv is set up then this may be a permissions issue. In bash, -you can use `ls -l /dev/kvm` or `ls -l /dev/mshv` to check which group owns that device and then `groups` to make sure -your user is a member of that group. - -For more details on how to verify that KVM is correctly installed and permissions are correct, follow the -guide [here](https://help.ubuntu.com/community/KVM/Installation). - -For additional debugging tips, including common build and runtime issues, see the [How to build a Hyperlight guest binary](./docs/how-to-build-a-hyperlight-guest-binary.md) guide. - -### Or you can use a codespace +Or skip setup entirely with a codespace: [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/hyperlight-dev/hyperlight) -## Contributing to Hyperlight - -If you are interested in contributing to Hyperlight, running the entire test-suite is a good way to get started. To do -so, on your console, run the following commands: - -```sh -just guests # build the c and rust test guests -just build # build the Hyperlight library -just test # runs the tests -``` - -Also , please review the [CONTRIBUTING.md](./CONTRIBUTING.md) file for more information on how to contribute to -Hyperlight. - -> Note: For general Hyperlight development, you may also need flatc (Flatbuffer compiler): for instructions, -> see [here](https://github.com/google/flatbuffers). -> Copyright © contributors to Hyperlight, established as Hyperlight a Series of LF Projects, LLC. - -## Join our Community Meetings - -This project holds fortnightly community meetings to discuss the project's progress, roadmap, and any other topics of interest. The meetings are open to everyone, and we encourage you to join us. - -- **When**: Every other Wednesday 09:00 (PST/PDT) [Convert to your local time](https://dateful.com/convert/pst-pdt-pacific-time?t=09) -- **Where**: Zoom! - Agenda and information on how to join can be found in the [Hyperlight Community Meeting Notes](https://hackmd.io/blCrncfOSEuqSbRVT9KYkg#Agenda). Please log into hackmd to edit! - -## Chat with us on the CNCF Slack - -The Hyperlight project Slack is hosted in the CNCF Slack #hyperlight. To join the Slack, [join the CNCF Slack](https://www.cncf.io/membership-faq/#how-do-i-join-cncfs-slack), and join the #hyperlight channel. - -## More Information - -For more information, please refer to our compilation of documents in the [`docs/` directory](./docs/README.md). - -## Code of Conduct - -See the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). - -[wsl2]: https://docs.microsoft.com/en-us/windows/wsl/install - -[kvm]: https://help.ubuntu.com/community/KVM/Installation +## Repository Structure -[whp]: https://devblogs.microsoft.com/visualstudio/hyper-v-android-emulator-support/#1-enable-hyper-v-and-the-windows-hypervisor-platform +| Directory | Description | +|---|---| +| [src/hyperlight_host](./src/hyperlight_host) | Host library - creates and manages micro VMs | +| [src/hyperlight_guest](./src/hyperlight_guest) | Core guest library - minimal building blocks for guest-host interaction | +| [src/hyperlight_guest_bin](./src/hyperlight_guest_bin) | Extended guest library - entry point, panic handler, heap, logging, exceptions | +| [src/hyperlight_guest_capi](./src/hyperlight_guest_capi) | C API wrapper around `hyperlight_guest_bin` for use via FFI | +| [src/hyperlight_libc](./src/hyperlight_libc) | C standard library for guests, built from picolibc | +| [src/hyperlight_guest_macro](./src/hyperlight_guest_macro) | Macros for registering guest and host functions | +| [src/hyperlight_guest_tracing](./src/hyperlight_guest_tracing) | Tracing support for guests | +| [src/hyperlight_common](./src/hyperlight_common) | Shared code used by both host and guest | +| [src/hyperlight_component_macro](./src/hyperlight_component_macro) | Proc macros for WIT-based host/guest bindings | +| [src/hyperlight_component_util](./src/hyperlight_component_util) | Shared implementation for WIT binding generation | +| [src/hyperlight_testing](./src/hyperlight_testing) | Shared test utilities | +| [src/schema](./src/schema) | FlatBuffer schema definitions | +| [src/trace_dump](./src/trace_dump) | Tool for dumping and visualizing trace data | +| [src/tests](./src/tests) | Test guest programs (Rust and C) | + +## Related Projects + +- [cargo-hyperlight](https://github.com/hyperlight-dev/cargo-hyperlight) - Cargo subcommand for building and scaffolding Hyperlight guests +- [hyperlight-wasm](https://github.com/hyperlight-dev/hyperlight-wasm) - Run WebAssembly modules inside Hyperlight micro VMs +- [hyperlight-js](https://github.com/hyperlight-dev/hyperlight-js) - Run JavaScript inside Hyperlight micro VMs +- [hyperlight-sandbox](https://github.com/hyperlight-dev/hyperlight-sandbox) - Multi-backend sandboxing framework for running untrusted code with controlled host capabilities, with Python, .NET, and Rust SDKs +- [hyperlight-unikraft](https://github.com/hyperlight-dev/hyperlight-unikraft) - Run Linux applications (Python, Node.js, Go, Rust, C/C++) on Hyperlight micro VMs using Unikraft as the guest kernel + +## Contributing + +See [CONTRIBUTING.md](./CONTRIBUTING.md). + +## Community + +- **Meetings**: Every other Wednesday 09:00 PST/PDT ([convert to your time](https://dateful.com/convert/pst-pdt-pacific-time?t=09)). Agenda and join info in the [Community Meeting Notes](https://hackmd.io/blCrncfOSEuqSbRVT9KYkg#Agenda). +- **Slack**: [#hyperlight](https://cloud-native.slack.com/archives/hyperlight) on CNCF Slack ([join here](https://www.cncf.io/membership-faq/#how-do-i-join-cncfs-slack)). +- **Docs**: [`docs/` directory](./docs/README.md) +- **Code of Conduct**: [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md) +--- -## FOSSA Status [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fhyperlight-dev%2Fhyperlight.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fhyperlight-dev%2Fhyperlight?ref=badge_large) diff --git a/docs/README.md b/docs/README.md index 3b36c5db1..d99173756 100644 --- a/docs/README.md +++ b/docs/README.md @@ -24,6 +24,7 @@ This project is composed internally of several components, depicted in the below ## Further reading +* [Getting Started](./getting-started.md) * [Glossary](./glossary.md) * [How code gets executed in a VM](./hyperlight-execution-details.md) * [How to build a Hyperlight guest binary](./how-to-build-a-hyperlight-guest-binary.md) diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 000000000..09c9e242a --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,155 @@ +# Getting Started with Hyperlight + +This guide covers everything you need to start using Hyperlight in your own project. + +## Prerequisites to run Hyperlight + +These are the minimum requirements to use Hyperlight as a library in your own project. + +- **A supported hypervisor:** + - Linux: [KVM](https://help.ubuntu.com/community/KVM/Installation) or Microsoft Hypervisor (MSHV) + - Windows: [Windows Hypervisor Platform](https://docs.microsoft.com/en-us/virtualization/api/#windows-hypervisor-platform) (WHP) +- **[Rust](https://www.rust-lang.org/tools/install)**, installed via `rustup`. +- **Platform build tools** (provides the C linker required by Rust): + - Ubuntu/Debian: `sudo apt install build-essential` + - Azure Linux: `sudo dnf install build-essential` + - Windows: Visual Studio Build Tools with the C++ workload and the Windows SDK. `rustup` prompts you to install them if missing. + +### Building guest binaries + +If you're writing Hyperlight guest programs (not just using the host library), you'll also need: + +- **Clang/LLVM** (see [platform-specific instructions](#platform-specific-setup) below) +- **[cargo-hyperlight](https://github.com/hyperlight-dev/cargo-hyperlight)** - install via `cargo install --locked cargo-hyperlight` + +## Platform-specific setup + +### Windows + +Requires Windows 11 Pro/Enterprise/Education or Windows Server 2025 or later. + +1. Enable the Windows Hypervisor Platform (requires a reboot): + + ```powershell + Enable-WindowsOptionalFeature -Online -FeatureName HypervisorPlatform -NoRestart + ``` + +2. If building guest binaries, install Clang/LLVM via the Visual Studio installer (installed by `rustup`): + + ```powershell + $vsPath = & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -property installationPath + & "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe" modify ` + --installPath $vsPath ` + --add Microsoft.VisualStudio.Component.VC.Llvm.Clang ` + --quiet --norestart + ``` + +### Ubuntu / Debian + +1. Install build tools: + + ```sh + sudo apt install build-essential + ``` + +2. Ensure KVM is available and your user has access: + + ```sh + ls -l /dev/kvm + # If needed, add yourself to the kvm group: + sudo usermod -aG kvm $USER + ``` + + For more details, see the [KVM installation guide](https://help.ubuntu.com/community/KVM/Installation). + +3. If building guest binaries, install LLVM/Clang: + + ```sh + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 18 + ``` + + The LLVM binaries are installed to `/usr/lib/llvm-18/bin/`. You may want to add this to your PATH: + + ```sh + echo 'export PATH=/usr/lib/llvm-18/bin:$PATH' >> ~/.bashrc + source ~/.bashrc + ``` + +### Azure Linux + +1. Install build tools: + + ```sh + sudo dnf install build-essential + ``` + +2. Ensure mshv is available (`/dev/mshv`). + +3. If building guest binaries, install clang: + + ```sh + sudo dnf install clang + ``` + +### WSL2 + +Follow the Ubuntu/Debian instructions above inside your WSL2 instance. WSL2 uses KVM. +See [install WSL](https://learn.microsoft.com/en-us/windows/wsl/install) for setup instructions. + +## Quick start + +The easiest way to get started is to use the `cargo hyperlight new` command. This creates a ready-to-build project with both a host application and a guest binary: + +```sh +cargo install --locked cargo-hyperlight +cargo hyperlight new my-project +``` + +Build and run: + +```sh +cd my-project/guest && cargo hyperlight build +cd ../host && cargo run +``` + +You should see: + +```text +Hello, World! Today is Monday. +2 + 3 = 5 +count = 1 +count = 2 +count = 3 +count after restore = 1 +``` + +> **Note:** If you modify the guest code, remember to rebuild it with `cargo hyperlight build` before running the host again. The host loads the guest binary from disk, so changes won't take effect until the guest is recompiled. + +## Troubleshooting + +If you get `Error: NoHypervisorFound`, check that your hypervisor device exists and is accessible: + +**Linux:** + +```sh +ls -l /dev/kvm +ls -l /dev/mshv +``` + +Verify your user is in the owning group with `groups`. If not, add yourself (e.g., `sudo usermod -aG kvm $USER`) and log out/in. + +**Windows** (Admin PowerShell): + +```powershell +Get-WindowsOptionalFeature -Online | Where-Object {$_.FeatureName -match 'Hyper-V|HypervisorPlatform|VirtualMachinePlatform'} | Format-Table +``` + +For additional debugging tips, see [How to build a Hyperlight guest binary](./how-to-build-a-hyperlight-guest-binary.md). + +## Or use a codespace + +Skip all setup and use a preconfigured environment: + +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/hyperlight-dev/hyperlight) diff --git a/docs/how-to-build-a-hyperlight-guest-binary.md b/docs/how-to-build-a-hyperlight-guest-binary.md index 2d79c967e..b48e2ea1e 100644 --- a/docs/how-to-build-a-hyperlight-guest-binary.md +++ b/docs/how-to-build-a-hyperlight-guest-binary.md @@ -2,51 +2,138 @@ This document explains how to build a binary to be used as a Hyperlight guest. -When building a guest, one needs to follow some rules so that the resulting -binary can be used with Hyperlight: -- the binary must not use the standard library -- the expected entrypoint function signature is `void hyperlight_main(void)` or - `pub fn hyperlight_main()` -- Hyperlight expects - `hl_Vec* c_guest_dispatch_function(const hl_FunctionCall *functioncall)` or - `pub fn guest_dispatch_function(function_call: FunctionCall) -> Result>` - to be defined in the binary so that in case the host calls a function that is - not registered by the guest, this function is called instead. -- to be callable by the host, a function needs to be registered by the guest in - the `hyperlight_main` function. +A Hyperlight guest is a regular ELF binary built for a custom target. It runs +without an operating system, exposes functions that the host can call, and may +call functions registered by the host. Builds use `cargo hyperlight build`, +which sets up the target, sysroot, and environment variables. + +Install [`cargo-hyperlight`](https://github.com/hyperlight-dev/cargo-hyperlight) +with: + +```sh +cargo install --locked cargo-hyperlight +``` + +To scaffold a working host plus guest project, run: + +```sh +cargo hyperlight new my-project +``` + +Pass `--no-host` to generate only a guest crate, or `--no-guest` to generate +only a host crate. + +The rest of this document explains what the generated guest contains and how to +build one by hand. ## Rust guest binary -In the case of a binary that is written in Rust, one needs to make use of the -Hyperlight crate, `hyperlight_guest` and `hyperlight_guest_bin` that contains the types and APIs that enable -the guest to: -- register functions that can be called by the host application -- call host functions that have been registered by the host. +### Minimal guest + +A minimal Rust guest depends only on `hyperlight-guest-bin` and uses its +attribute macros to register guest functions and declare host functions. + +`Cargo.toml`: + +```toml +[package] +name = "my-guest" +version = "0.1.0" +edition = "2024" + +[dependencies] +hyperlight-guest-bin = "*" # use the latest version from crates.io +``` + +`src/main.rs`: + +```rust +#![no_std] +#![no_main] +extern crate alloc; + +use alloc::string::String; + +use hyperlight_guest_bin::error::Result; +use hyperlight_guest_bin::{guest_function, host_function}; -### Requirements +// Declare a host function the guest can call. The string is the name the +// host registered it under. If omitted, the Rust function name is used. +#[host_function("GetWeekday")] +fn get_weekday() -> Result; -- **`#![no_std]`**: Hyperlight guests run in a minimal environment without an operating system -- **`#![no_main]`**: The entry point is `hyperlight_main`, not the standard `main` function -- **`extern crate alloc`**: Required for heap allocations (Vec, String, etc.) -- **`extern crate hyperlight_guest_bin`**: Required to link the guest runtime (panic handler, etc.) +// Register a guest function the host can call. +#[guest_function("SayHello")] +fn say_hello(name: String) -> Result { + let weekday = get_weekday()?; + Ok(alloc::format!("Hello, {name}! Today is {weekday}.")) +} +``` + +Build with: + +```sh +cargo hyperlight build +``` + +The resulting binary in `target/x86_64-hyperlight-none//my-guest` is +what the host loads with `GuestBinary::FilePath(...)`. + +#### What the macros generate + +* `#[guest_function]` registers the function with the guest runtime so the host + can call it by name. Argument and return types must be supported parameter + and return types, or `Result` wrapping one. +* `#[host_function]` turns an `extern`-style signature into a stub that + marshals arguments to the host and returns the host's reply. +* The runtime provides a default `hyperlight_main` entry point and a default + dispatch function. You do not need to write either one for a typical guest. + +#### Required attributes + +* `#![no_std]` because there is no operating system in the guest. +* `#![no_main]` because the entry point is `hyperlight_main`, not `main`. +* `extern crate alloc` to use `Vec`, `String`, and other heap types. + +### Advanced: manual entry point and dispatch + +The macros are optional. A guest can define the underlying symbols directly, +which is useful for advanced setup work or custom dispatch logic (for example +the WIT-based guests in `src/tests/rust_guests/witguest`). + +The host expects two guest symbols: + +* `pub extern "C" fn hyperlight_main()` runs once at guest startup. Use it to + register functions or initialize global state. +* `pub extern "Rust" fn guest_dispatch_function(function_call: FunctionCall) -> Result, HyperlightGuestError>` + is invoked when the host calls a function name that is not registered. + +`hyperlight-guest-bin` exposes `#[main]` and `#[dispatch]` macros that generate +these symbols from a regular Rust function, so most "advanced" guests still use +the macros rather than writing the raw `extern "C"` items themselves. + +If you mix the manual form with `#[guest_function]`, registrations from the +macro still happen automatically. Your `hyperlight_main` only needs to do +whatever extra setup the macros do not cover. ### Troubleshooting #### "duplicate lang item `panic_impl`" error -This error occurs when the standard library's panic handler conflicts with -`hyperlight_guest_bin`'s panic handler. To fix this: +This error means the standard library's panic handler is being linked +alongside `hyperlight_guest_bin`'s. To fix: -1. Ensure `hyperlight-common` has `default-features = false` in your `Cargo.toml` -2. Make sure your crate has `#![no_std]` at the top of `main.rs` -3. Run `cargo clean` to clear any stale build artifacts -4. Use `cargo hyperlight build` instead of `cargo build` +1. Ensure your crate has `#![no_std]` at the top of `main.rs`. +2. Confirm any transitive dependency on `hyperlight-common` uses + `default-features = false`. +3. Run `cargo clean` to clear stale artifacts. +4. Build with `cargo hyperlight build`, not `cargo build`. #### Build errors with dependencies -If you see errors related to building dependencies (like serde), ensure you're using -`cargo hyperlight build`. This sets up the proper environment variables and sysroot -for the custom Hyperlight target. +If you see errors building dependencies (such as `serde`), make sure you are +using `cargo hyperlight build`. It sets up the environment variables and +sysroot needed for the custom Hyperlight target. ## C guest binary @@ -56,6 +143,9 @@ C API library. The `hyperlight_guest.h` header contains the corresponding APIs to register guest functions and call host functions from within the guest. +See [src/tests/c_guests/c_simpleguest/main.c](../src/tests/c_guests/c_simpleguest/main.c) +for a complete example. + ## Version compatibility Guest binaries built with `hyperlight-guest-bin` automatically embed the crate