Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
6 changes: 3 additions & 3 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 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,25 @@ limitations under the License.

use alloc::string::String;
use alloc::vec;
use core::ffi::*;
use core::ffi::{c_int, c_long, c_void};
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, clockid_t, errno, timespec,
timeval,
};

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 +43,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 +58,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 +85,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,7 +113,7 @@ 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 {
extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut c_void) -> c_int {
if tv.is_null() {
set_errno(EINVAL);
return -1;
Expand All @@ -146,17 +128,17 @@ pub extern "C" fn gettimeofday(tv: *mut Timeval, _tz: *mut c_void) -> c_int {
}

#[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