Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/RustNightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
src/tests/rust_guests/witguest -> target

- name: Install cargo-hyperlight
run: cargo install cargo-hyperlight --version 0.1.9 --locked --force
run: cargo install cargo-hyperlight --version 0.1.10 --locked --force

- name: Build and move Rust guests
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dep_build_guests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
src/tests/rust_guests/witguest -> target

- name: Install cargo-hyperlight
run: cargo install cargo-hyperlight --version 0.1.9 --locked --force
run: cargo install cargo-hyperlight --version 0.1.10 --locked --force

- name: Build Rust guests
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/dep_code_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
run: just fmt-check

- name: Install cargo-hyperlight
run: cargo install cargo-hyperlight --version 0.1.9 --locked --force
run: cargo install cargo-hyperlight --version 0.1.10 --locked --force

- name: clippy exhaustive check (debug)
run: just clippy-exhaustive debug
Expand Down Expand Up @@ -145,7 +145,7 @@ jobs:
run: just fmt-check

- name: Install cargo-hyperlight
run: cargo install cargo-hyperlight --version 0.1.9 --locked --force
run: cargo install cargo-hyperlight --version 0.1.10 --locked --force

- name: clippy (debug)
run: |
Expand Down
4 changes: 2 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "src/hyperlight_guest_bin/third_party/picolibc"]
path = src/hyperlight_guest_bin/third_party/picolibc
[submodule "src/hyperlight_libc/third_party/picolibc"]
path = src/hyperlight_libc/third_party/picolibc
url = https://github.com/hyperlight-dev/picolibc-bsd.git
shallow = true
35 changes: 31 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ members = [
"fuzz",
"src/hyperlight_guest_bin",
"src/hyperlight_guest_macro",
"src/hyperlight_libc",
"src/hyperlight_component_util",
"src/hyperlight_component_macro",
"src/trace_dump",
Expand Down Expand Up @@ -43,6 +44,7 @@ hyperlight-guest-bin = { path = "src/hyperlight_guest_bin", version = "0.14.0",
hyperlight-guest-macro = { path = "src/hyperlight_guest_macro", version = "0.14.0", default-features = false }
hyperlight-testing = { path = "src/hyperlight_testing", default-features = false }
hyperlight-guest-tracing = { path = "src/hyperlight_guest_tracing", version = "0.14.0", default-features = false }
hyperlight-libc = { path = "src/hyperlight_libc", version = "0.14.0", default-features = false }
hyperlight-component-util = { path = "src/hyperlight_component_util", version = "0.14.0", default-features = false }
hyperlight-component-macro = { path = "src/hyperlight_component_macro", version = "0.14.0", default-features = false }

Expand Down
2 changes: 1 addition & 1 deletion NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Copyright © 2020 The Newlib Project
Newlib code is licensed under a collection of BSD-compatible and
permissive licenses. The full license details for all files are
documented in the COPYING.picolibc and COPYING.NEWLIB files in the
picolibc submodule at src/hyperlight_guest_bin/third_party/picolibc/.
picolibc submodule at src/hyperlight_libc/third_party/picolibc/.

Note: The picolibc submodule uses the picolibc-bsd fork
(https://github.com/hyperlight-dev/picolibc-bsd), which is a redistribution
Expand Down
2 changes: 1 addition & 1 deletion c.just
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mkdir := if os() == "windows" { "mkdir -f -p" } else { "mkdir -p"}
# Elf options
# We don't support stack protectors at the moment, but Arch Linux clang auto-enables them for -linux platforms, so explicitly disable them.
c-compile-options-elf := '-nostdlibinc -H --target=x86_64-unknown-linux-none -fno-stack-protector -fstack-clash-protection -mstack-probe-size=4096 -fPIC'
c-include-flags-elf := "-I " + root / "src/hyperlight_guest_capi/include/" + " -I " + root / "src/hyperlight_guest_bin/third_party/picolibc/libc/include/" + " -I " + root / "src/hyperlight_guest_bin/third_party/picolibc/libc/stdio/" + " -I " + root / "src/hyperlight_guest_bin/include/"
c-include-flags-elf := "-I " + root / "src/hyperlight_guest_capi/include/" + " -I " + root / "src/hyperlight_libc/third_party/picolibc/libc/include/" + " -I " + root / "src/hyperlight_libc/third_party/picolibc/libc/stdio/" + " -I " + root / "src/hyperlight_libc/include/"
c-linker-options-elf := '--entry "entrypoint" --nostdlib -pie --no-dynamic-linker'
c-flags-debug-elf := '-O0'
c-flags-release-elf := '-O3'
Expand Down
8 changes: 4 additions & 4 deletions docs/picolibc.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ for embedded systems, making it well-suited for Hyperlight's micro-VM environmen

The picolibc integration is controlled by the `libc` feature flag on the `hyperlight-guest-bin`
crate (enabled by default). When enabled, the build script compiles picolibc from source using the
vendored submodule at `src/hyperlight_guest_bin/third_party/picolibc`.
vendored submodule at `src/hyperlight_libc/third_party/picolibc`.

The submodule points to [picolibc-bsd](https://github.com/hyperlight-dev/picolibc-bsd), a
redistribution of picolibc with all copyleft-licensed files (GPL/AGPL) removed from the tree and
Expand All @@ -17,7 +17,7 @@ licensing details.

## Host Function Stubs

When the `libc` feature is enabled, the POSIX stubs in `src/hyperlight_guest_bin/src/libc.rs`
When the `libc` feature is enabled, the POSIX stubs in `src/hyperlight_guest_bin/src/libc_stubs.rs`
provide C-compatible implementations of `read`, `write`, `clock_gettime`, `gettimeofday`, and other
functions that picolibc calls internally.

Expand Down Expand Up @@ -66,11 +66,11 @@ To update picolibc to a new version:
2. Update the submodule in hyperlight:

```bash
cd src/hyperlight_guest_bin/third_party/picolibc
cd src/hyperlight_libc/third_party/picolibc
git fetch origin
git checkout <new-fork-tag>
cd ../../../..
git add src/hyperlight_guest_bin/third_party/picolibc
git add src/hyperlight_libc/third_party/picolibc
```

3. Verify licensing: The fork's CI runs scancode-toolkit to ensure no copyleft files are present.
Expand Down
2 changes: 0 additions & 2 deletions src/hyperlight_guest_bin/.cargo/config.toml

This file was deleted.

10 changes: 2 additions & 8 deletions src/hyperlight_guest_bin/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[package]
name = "hyperlight-guest-bin"
links = "c"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
Expand All @@ -15,7 +14,7 @@ and third-party code used by our C-API needed to build a native hyperlight-guest

[features]
default = ["libc", "macros"]
libc = [] # compile libc from picolibc
libc = ["dep:hyperlight-libc"] # compile libc from picolibc
trace_guest = ["hyperlight-common/trace_guest", "hyperlight-guest/trace_guest", "hyperlight-guest-tracing/trace"]
mem_profile = ["hyperlight-common/mem_profile"]
macros = ["dep:hyperlight-guest-macro", "dep:linkme"]
Expand All @@ -25,6 +24,7 @@ hyperlight-guest = { workspace = true, default-features = false }
hyperlight-common = { workspace = true, default-features = false }
hyperlight-guest-tracing = { workspace = true, default-features = false }
hyperlight-guest-macro = { workspace = true, default-features = false, optional = true }
hyperlight-libc = { workspace = true, default-features = false, optional = true }
buddy_system_allocator = "0.13.0"
log = { version = "0.4", default-features = false }
linkme = { version = "0.3.36", optional = true }
Expand All @@ -34,9 +34,3 @@ tracing = { version = "0.1.44", default-features = false, features = ["attribute

[lints]
workspace = true

[build-dependencies]
anyhow = "1"
cc = "1.2"
cfg-if = "1.0"
glob = "0.3.3"
7 changes: 6 additions & 1 deletion src/hyperlight_guest_bin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,13 @@ pub mod memory;
pub mod paging;

/// Bridge between picolibc's POSIX expectations and the Hyperlight host.
/// cbindgen:ignore
#[cfg(feature = "libc")]
mod libc;
mod libc_stubs;

/// Re-export the libc bindings from hyperlight-libc when the libc feature is enabled.
#[cfg(feature = "libc")]
pub use hyperlight_libc as libc;
Comment thread
jprendes marked this conversation as resolved.

// Globals
#[cfg(all(feature = "mem_profile", target_arch = "x86_64"))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,48 +16,24 @@ limitations under the License.

use alloc::string::String;
use alloc::vec;
use core::ffi::*;
use core::sync::atomic::{AtomicU64, Ordering};

use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};

use crate::host_comm::call_host_function;
use crate::libc::{
CLOCK_MONOTONIC, CLOCK_REALTIME, EBADF, EINVAL, EIO, ENOSYS, c_int, c_long, c_void, clockid_t,
errno, timespec,
};

unsafe extern "C" {
static mut errno: c_int;
}

fn set_errno(val: c_int) {
fn set_errno(val: u32) {
// SAFETY: single-threaded guest, errno is a global int (__GLOBAL_ERRNO)
unsafe { errno = val };
// Bindgen uses u32 for the errno definitions, so we convert it to the expected c_int type here
unsafe { errno = val as _ };
}

// POSIX errno values (matching picolibc sys/errno.h)
const EINVAL: c_int = 22;
const EIO: c_int = 5;
const EBADF: c_int = 9;
const ENOSYS: c_int = 88;

// picolibc clock IDs (from time.h)
const CLOCK_REALTIME: c_ulong = 1;
const CLOCK_MONOTONIC: c_ulong = 4;

static CURRENT_TIME: AtomicU64 = AtomicU64::new(0);

/// Matches picolibc `struct timespec` layout for x86_64 and aarch64.
#[repr(C)]
pub(crate) struct Timespec {
tv_sec: c_long,
tv_nsec: c_long,
}

/// Matches picolibc `struct timeval` layout for x86_64 and aarch64.
#[repr(C)]
pub(crate) struct Timeval {
tv_sec: c_long,
tv_usec: c_long,
}

/// Returns a synthetic monotonically-increasing time starting at Unix epoch
/// increasing 1s each call.
fn current_time() -> (u64, u64) {
Expand All @@ -66,7 +42,7 @@ fn current_time() -> (u64, u64) {
}

#[unsafe(no_mangle)]
pub extern "C" fn read(fd: c_int, buf: *mut c_void, count: usize) -> isize {
extern "C" fn read(fd: c_int, buf: *mut c_void, count: usize) -> isize {
if buf.is_null() && count > 0 {
set_errno(EINVAL);
return -1;
Expand All @@ -81,7 +57,7 @@ pub extern "C" fn read(fd: c_int, buf: *mut c_void, count: usize) -> isize {
}

#[unsafe(no_mangle)]
pub extern "C" fn write(fd: c_int, buf: *const c_void, count: usize) -> isize {
extern "C" fn write(fd: c_int, buf: *const c_void, count: usize) -> isize {
if buf.is_null() && count > 0 {
set_errno(EINVAL);
return -1;
Expand All @@ -108,14 +84,19 @@ pub extern "C" fn write(fd: c_int, buf: *const c_void, count: usize) -> isize {
}

#[unsafe(no_mangle)]
pub extern "C" fn clock_gettime(clk_id: c_ulong, tp: *mut Timespec) -> c_int {
extern "C" fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
// The libc bindings generated by bindgen are u32, but we expect them to be clockid_t,
// so we convert the constants to the expected type here for comparison.
const CLOCK_ID_REALTIME: clockid_t = CLOCK_REALTIME as _;
const CLOCK_ID_MONOTONIC: clockid_t = CLOCK_MONOTONIC as _;

if tp.is_null() {
set_errno(EINVAL);
return -1;
}

match clk_id {
CLOCK_REALTIME | CLOCK_MONOTONIC => {
CLOCK_ID_REALTIME | CLOCK_ID_MONOTONIC => {
let (secs, nanos) = current_time();
unsafe {
(*tp).tv_sec = secs as c_long;
Expand All @@ -131,32 +112,17 @@ pub extern "C" fn clock_gettime(clk_id: c_ulong, tp: *mut Timespec) -> c_int {
}

#[unsafe(no_mangle)]
pub extern "C" fn gettimeofday(tv: *mut Timeval, _tz: *mut c_void) -> c_int {
if tv.is_null() {
set_errno(EINVAL);
return -1;
}

let (secs, nanos) = current_time();
unsafe {
(*tv).tv_sec = secs as c_long;
(*tv).tv_usec = (nanos / 1000) as c_long;
}
0
}

#[unsafe(no_mangle)]
pub extern "C" fn _exit(ec: c_int) -> ! {
extern "C" fn _exit(ec: c_int) -> ! {
hyperlight_guest::exit::abort_with_code(&[ec as u8]);
}

#[unsafe(no_mangle)]
pub extern "C" fn lseek(_fd: c_int, _offset: c_long, _whence: c_int) -> c_long {
extern "C" fn lseek(_fd: c_int, _offset: c_long, _whence: c_int) -> c_long {
set_errno(ENOSYS);
-1
}

#[unsafe(no_mangle)]
pub extern "C" fn close(_fd: c_int) -> c_int {
extern "C" fn close(_fd: c_int) -> c_int {
0
}
29 changes: 29 additions & 0 deletions src/hyperlight_libc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

[package]
name = "hyperlight-libc"
links = "c"
Comment thread
jprendes marked this conversation as resolved.
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
readme.workspace = true
description = """
This crate provides picolibc for Hyperlight guests.
It builds the picolibc library and generates bindings to the libc types and functions.
"""

[features]
default = []

[dependencies]

[lints]
workspace = true

[build-dependencies]
anyhow = "1"
cc = "1.2"
glob = "0.3.3"
bindgen = { version = "0.71", features = ["prettyplease"] }
Loading
Loading