Skip to content

RustyHermit - A Rust-based, lightweight unikernel

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

mustermeiszer/rusty-hermit

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RustyHermit - A Rust-based, lightweight unikernel

Build Status Build Status Actions Status Slack Status

RustyHermit is a unikernel targeting a scalable and predictable runtime for high-performance and cloud computing. Unikernel means, you bundle your application directly with the kernel library, so that it can run without any installed operating system. This reduces overhead, therefore, interesting applications include virtual machines and high-performance computing.

The kernel is able to run Rust applications, as well as C/C++/Go/Fortran applications.

The repository contains following directories and submodules:

  1. demo is a small demo application based on the data-parallelism library Rayon
  2. hermit-abi contains the platform APIs and builds the interface between library operating system and the application
  3. hermit-sys contains a crate to automate the build process of the library operating systems
  4. libhermit-rs is the kernel itself
  5. loader contains a loader to run RustyHermit on a common virtualization platforms (Qemu) or bare-mateal on a x86 system
  6. netbench provides some basic network benchmarks

Background

RustyHermit is a rewrite of HermitCore in Rust developed at RWTH-Aachen. HermitCore was a research unikernel written in C (libhermit).

The ownership model of Rust guarantees memory/thread-safety and enables us to eliminate many classes of bugs at compile-time. Consequently, the use of Rust for kernel development promises less vulnerabilities in comparison to common programming languages.

The kernel and the integration into the Rust runtime are entirely written in Rust and do not use any C/C++ Code. We extended the Rust toolchain so that the build process is similar to Rust's usual workflow. Rust applications that use the Rust runtime and do not directly use OS services are able to run on RustyHermit without modifications.

Prerequisites

The Rust toolchain can be installed from the official webpage. RustyHermit currently requires the nightly versions of the toolchain.

$ rustup default nightly

Further requirements are the source code of the Rust runtime, cargo-download, and llvm-tools:

$ cargo install cargo-download
$ rustup component add rust-src
$ rustup component add llvm-tools-preview

Building your own applications

To give you an example on how to build your application with RustyHermit, lets create a new cargo project: A more comprehensive version of the example project is published at rusty-demo.

cargo new hello_world
cd hello_world

To bind the library operating system to the application, add the crate hermit-sys to the dependencies in the file Cargo.toml. It is important to use at least the optimization level 1. Consequently, it is required to extend Cargo.toml with following lines:

# Cargo.toml

[target.'cfg(target_os = "hermit")'.dependencies]
hermit-sys = "0.1.*"

[profile.release]
opt-level = 3

[profile.dev]
opt-level = 1

To link the application with RustyHermit, declare hermit_sys an external crate in the main file of your application.

// src/main.rs

#[cfg(target_os = "hermit")]
extern crate hermit_sys;

fn main() {
        println!("Hello World!");
}

The final step is building the application as follows:

cargo build -Z build-std=std,core,alloc,panic_abort --target x86_64-unknown-hermit

(You can set an easy alias for this in the .cargo/config file. Take a look at the demo)

The resulting "hypervisor-ready" binary then can be found in target/x86_64-unknown-hermit/debug.

Running RustyHermit

RustyHermit binaries can be run on either uhyve or qemu.

Using uhyve as Hypervisor

RustyHermit can run within our own hypervisor uhyve , which requires KVM to create a virtual machine. Please install the hypervisor as follows:

cargo install uhyve

Afterwards, your are able to start RustyHermit applications within our hypervisor:

uhyve target/x86_64-unknown-hermit/debug/rusty_demo

More details can be found in the uhyve README.

Using Qemu as Hypervisor

It is also possible to run RustyHermit within Qemu. RustyHermit produces 64-bit binaries, but Qemu's x86 emulation cannot boot them directly. Therefore, the loader rusty-loader is required to boot the application. To build the loader, the assembler nasm is required. After the installation, the loader can be build as follows.

$ git clone https://github.com/hermitcore/rusty-loader.git
$ cd rusty-loader
$ make

Afterwards, the loader is stored in target/x86_64-unknown-hermit-loader/debug/ as rusty-loader. As final step, the unikernel application app can be booted with following command:

$ qemu-system-x86_64 -display none -smp 1 -m 64M -serial stdio  -kernel path_to_loader/rusty-loader -initrd path_to_app/app -cpu qemu64,apic,fsgsbase,rdtscp,xsave,fxsr

It is important to enable the processor features fsgsbase and rdtscp because it is a prerequisite to boot RustyHermit.

You can provide arguments to the application via the kernel commandline, which you can set with qemu's -append option. Since both the kernel and the application can have parameters, they are separated with --:

qemu-system-x86_64 ... -append "kernel-arguments -- application-arguments"

Advanced Features

You are not happy with Hello World yet?

Link Time Optimization (LTO)

To enable Link Time Optimization (LTO), please extend the release configuration in Cargo.toml as follows:

# Cargo.toml
[profile.release]
opt-level = 3
lto = "thin"

In addition, the Linker-plugin LTO have to be enabled by setting the compiler flag linker-plugin-lto. In this case, the release version have to build as follows:

RUSTFLAGS="-Clinker-plugin-lto" cargo build -Z build-std=std,core,alloc,panic_abort --target x86_64-unknown-hermit --release

Controlling kernel message verbosity

RustyHermit uses the lightweight logging crate log to print kernel messages. If the environment variable HERMIT_LOG_LEVEL_FILTER is set at compile time to a string matching the name of a LevelFilter, then that value is used for the LevelFilter. If the environment variable is not set, or the name doesn't match, then LevelFilter::Info is used by default, which is the same as it was before.

For instance, the following command build RustyHermit with debug messages:

$ HERMIT_LOG_LEVEL_FILTER=Debug cargo build -Z build-std=std,core,alloc,panic_abort --target x86_64-unknown-hermit

Network support

To enable an ethernet device, we have to setup a tap device on the host system. For instance, the following command establish the tap device tap10 on Linux:

$ sudo ip tuntap add tap10 mode tap
$ sudo ip addr add 10.0.5.1/24 broadcast 10.0.5.255 dev tap10
$ sudo ip link set dev tap10 up
$ sudo bash -c 'echo 1 > /proc/sys/net/ipv4/conf/tap10/proxy_arp'

Add the feature smoltcp in the Cargo.toml. This includes the network stack smoltcp and offers TCP/UDP communication.

# Cargo.toml

[target.'cfg(target_os = "hermit")'.dependencies]
hermit-sys = "0.1.*"
default-features = false
features = ["smoltcp"]

Per default, RustyHermit's network interface uses 10.0.5.3 as IP address, 10.0.5.1 for the gateway and 255.255.255.0 as network mask. The default configuration could be overloaded at compile time by the environment variables HERMIT_IP, HERMIT_GATEWAY and HERMIT_MASK. For instance, the following command sets the IP address to 10.0.5.100.

$ HERMIT_IP="10.0.5.100" cargo build -Z build-std=std,core,alloc,panic_abort --target x86_64-unknown-hermit

Currently, RustyHermit does only support network interfaces through virtio. To use it, you have to start RustyHermit in Qemu with following command:

$ qemu-system-x86_64 -cpu qemu64,apic,fsgsbase,rdtscp,xsave,fxsr \
        -enable-kvm -display none -smp 1 -m 1G -serial stdio \
        -kernel path_to_loader/rusty-loader \
        -initrd path_to_app/app \
        -netdev tap,id=net0,ifname=tap10,script=no,downscript=no,vhost=on \
        -device virtio-net-pci,netdev=net0,disable-legacy=on

Using virtio-fs

The Kernel has rudimentary support for the virtio-fs shared file system. Currently only files, no folders are supported. To use it, you have to run a virtio-fs daemon and start qemu as described in Standalone virtio-fs usage:

# start virtiofsd in the background
$ sudo virtiofsd --thread-pool-size=1 --socket-path=/tmp/vhostqemu -o source=$(pwd)/SHARED_DIRECTORY
# give non-root-users access to the socket
$ sudo chmod 777 /tmp/vhostqemu
# start qemu with virtio-fs device.
# you might want to change the socket (/tmp/vhostqemu) and virtiofs tag (currently myfs)
$ qemu-system-x86_64 -cpu qemu64,apic,fsgsbase,rdtscp,xsave,fxsr -enable-kvm -display none -smp 1 -m 1G -serial stdio \
        -kernel path_to_loader/rusty-loader \
        -initrd path_to_app/app \
        -chardev socket,id=char0,path=/tmp/vhostqemu \
        -device vhost-user-fs-pci,queue-size=1024,chardev=char0,tag=myfs \
        -object memory-backend-file,id=mem,size=1G,mem-path=/dev/shm,share=on \
        -numa node,memdev=mem

You can now access the files in SHARED_DIRECTORY under the virtiofs tag like /myfs/testfile.

Use RustyHermit for C/C++, Go, and Fortran applications

If you are interested to build C/C++, Go, and Fortran applications on top of a Rust-based library operating systen, please take a look at https://github.com/hermitcore/hermit-playground.

Missing features

  • Multikernel support (might be comming)
  • Virtio support (partly available)
  • Network support (partly available)

Troubleshooting

command failed with the error message linker rust-lld not found

The path to the llvm-tools is not set. On Linux, it is typically installed at ${HOME}/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin.

PATH=${HOME}/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:$PATH cargo build -Z build-std=std,core,alloc,panic_abort --target x86_64-unknown-hermit

Otherwise, the linker can be replaced by lld as follows:

RUSTFLAGS="-C linker=lld" cargo build -Z build-std=std,core,alloc,panic_abort --target x86_64-unknown-hermit

Credits

RustyHermit is derived from following tutorials and software distributions:

  1. Philipp Oppermann's excellent series of blog posts.
  2. Erik Kidd's toyos-rs, which is an extension of Philipp Opermann's kernel.
  3. The Rust-based teaching operating system eduOS-rs.

HermitCore's Emoji is provided for free by EmojiOne.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

RustyHermit is being developed on GitHub. Create your own fork, send us a pull request, and chat with us on Slack

About

RustyHermit - A Rust-based, lightweight unikernel

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust 98.6%
  • Dockerfile 1.4%