Skip to content

Commit 20195de

Browse files
committed
fix: get rid of host function probe
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
1 parent 3ad7116 commit 20195de

File tree

5 files changed

+47
-108
lines changed

5 files changed

+47
-108
lines changed

docs/picolibc.md

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,35 @@ script compiles picolibc from source using the vendored submodule at
1313
`src/hyperlight_guest_bin/third_party/picolibc`.
1414

1515
The build uses a sparse checkout to exclude GPL/AGPL-licensed test and script
16-
files only BSD/MIT/permissive-licensed source files are included. See
16+
files and only BSD/MIT/permissive-licensed source files are included. See
1717
`NOTICE.txt` for full licensing details.
1818

1919
## Host Function Stubs
2020

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

26-
These stubs can optionally delegate to host functions. If the host registers
27-
these functions, the corresponding libc functionality becomes available to
28-
guest code. If not registered, the stubs return appropriate errors.
26+
### Read (stdin)
2927

30-
| Host Function | Parameters | Return Type | Description |
31-
|-----------------|------------------------|-------------|-------------|
32-
| `HostPrint` | `String` | `Int` | Used by the `write()` stub. Only stdout (fd 1) and stderr (fd 2) are supported; both delegate to this single host function. Other file descriptors return `EBADF`. |
33-
| `HostRead` | `ULong` (byte count) | `VecBytes` | Used by the `read()` stub. Only stdin (fd 0) is supported; other file descriptors return `EBADF`. |
34-
| `CurrentTime` | _(none)_ | `VecBytes` | Used by `clock_gettime()` and `gettimeofday()`. Should return 16 bytes: 8 bytes of seconds + 8 bytes of nanoseconds. If not provided, a monotonic fallback starting at Unix timestamp `1609459200` (2021-01-01) is used. |
28+
The `read()` stub returns **EOF (0)** immediately for stdin (fd 0) without
29+
contacting the host. Other file descriptors return `EBADF`.
30+
31+
### Write (stdout / stderr)
32+
33+
The `write()` stub delegates to the `HostPrint` host function. Only stdout
34+
(fd 1) and stderr (fd 2) are supported; both map to the same `HostPrint`
35+
call, which accepts a `String` parameter and returns an `Int`. Other file
36+
descriptors return `EBADF`.
37+
38+
### Time
39+
40+
The `clock_gettime()`, `gettimeofday()`, and `_current_time()` stubs do
41+
**not** call out to the host. Instead they return a synthetic
42+
monotonically-increasing timestamp: the first call returns Unix epoch + 1 s
43+
(`1970-01-01 00:00:01`), the second returns epoch + 2 s, and so on. The
44+
nanosecond/microsecond component is always zero.
3545

3646
## Build Configuration
3747

src/hyperlight_guest_bin/src/host_comm.rs

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
use alloc::string::{String, ToString};
17+
use alloc::string::ToString;
1818
use alloc::vec::Vec;
19-
use core::ffi::{CStr, c_char};
20-
use core::mem;
2119

2220
use hyperlight_common::flatbuffer_wrappers::function_call::FunctionCall;
2321
use hyperlight_common::flatbuffer_wrappers::function_types::{
@@ -28,9 +26,6 @@ use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result;
2826
use hyperlight_common::func::{ParameterTuple, SupportedReturnType};
2927
use hyperlight_guest::error::{HyperlightGuestError, Result};
3028

31-
const BUFFER_SIZE: usize = 1000;
32-
static mut MESSAGE_BUFFER: Vec<u8> = Vec::new();
33-
3429
use crate::GUEST_HANDLE;
3530

3631
pub fn call_host_function<T>(
@@ -97,47 +92,3 @@ pub fn print_output_with_host_print(function_call: FunctionCall) -> Result<Vec<u
9792
))
9893
}
9994
}
100-
101-
/// Exposes a C API to allow the guest to print a string
102-
///
103-
/// # Safety
104-
/// This function is not thread safe
105-
#[unsafe(no_mangle)]
106-
#[allow(static_mut_refs)]
107-
pub unsafe extern "C" fn _putchar(c: c_char) {
108-
let handle = unsafe { GUEST_HANDLE };
109-
let char = c as u8;
110-
let message_buffer = unsafe { &mut MESSAGE_BUFFER };
111-
112-
// Extend buffer capacity if it's empty (like `with_capacity` in lazy_static).
113-
// TODO: replace above Vec::new() with Vec::with_capacity once it's stable in const contexts.
114-
if message_buffer.capacity() == 0 {
115-
message_buffer.reserve(BUFFER_SIZE);
116-
}
117-
118-
message_buffer.push(char);
119-
120-
if message_buffer.len() == BUFFER_SIZE || char == b'\0' {
121-
let str = if char == b'\0' {
122-
CStr::from_bytes_until_nul(message_buffer)
123-
.expect("No null byte in buffer")
124-
.to_string_lossy()
125-
.into_owned()
126-
} else {
127-
String::from_utf8(mem::take(message_buffer))
128-
.expect("Failed to convert buffer to string")
129-
};
130-
131-
// HostPrint returns an i32, but we don't care about the return value
132-
let _ = handle
133-
.call_host_function::<i32>(
134-
"HostPrint",
135-
Some(Vec::from(&[ParameterValue::String(str)])),
136-
ReturnType::Int,
137-
)
138-
.expect("Failed to call HostPrint");
139-
140-
// Clear the buffer after sending
141-
message_buffer.clear();
142-
}
143-
}

src/hyperlight_guest_bin/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub mod paging;
5353

5454
/// Bridge between picolibc's POSIX expectations and the Hyperlight host.
5555
#[cfg(feature = "libc")]
56-
mod host_bridge;
56+
mod libc;
5757

5858
// Globals
5959
#[cfg(feature = "mem_profile")]

src/hyperlight_guest_bin/src/host_bridge.rs renamed to src/hyperlight_guest_bin/src/libc.rs

Lines changed: 9 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ limitations under the License.
1616

1717
use alloc::string::String;
1818
use alloc::vec;
19-
use alloc::vec::Vec;
2019
use core::ffi::*;
2120
use core::sync::atomic::{AtomicU64, Ordering};
2221

@@ -45,33 +44,25 @@ const CLOCK_MONOTONIC: c_ulong = 4;
4544

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

48-
/// Matches picolibc `struct timespec` layout for x86_64.
47+
/// Matches picolibc `struct timespec` layout for x86_64 and aarch64.
4948
#[repr(C)]
5049
pub(crate) struct Timespec {
5150
tv_sec: c_long,
5251
tv_nsec: c_long,
5352
}
5453

55-
/// Matches picolibc `struct timeval` layout for x86_64.
54+
/// Matches picolibc `struct timeval` layout for x86_64 and aarch64.
5655
#[repr(C)]
5756
pub(crate) struct Timeval {
5857
tv_sec: c_long,
5958
tv_usec: c_long,
6059
}
6160

62-
/// Retrieves the current time from the host as (seconds, nanoseconds).
61+
/// Returns a synthetic monotonically-increasing time starting at Unix epoch
62+
/// increasing 1s each call.
6363
fn current_time() -> (u64, u64) {
64-
let bytes = call_host_function::<Vec<u8>>("CurrentTime", Some(vec![]), ReturnType::VecBytes)
65-
.unwrap_or_default();
66-
67-
if bytes.len() == 16 {
68-
let secs = u64::from_ne_bytes(bytes[0..8].try_into().unwrap());
69-
let nanos = u64::from_ne_bytes(bytes[8..16].try_into().unwrap());
70-
(secs, nanos)
71-
} else {
72-
let secs = 1609459200 + CURRENT_TIME.fetch_add(1, Ordering::Relaxed);
73-
(secs, 0)
74-
}
64+
let call_count = CURRENT_TIME.fetch_add(1, Ordering::Relaxed) + 1;
65+
(call_count, 0)
7566
}
7667

7768
#[unsafe(no_mangle)]
@@ -86,23 +77,9 @@ pub extern "C" fn read(fd: c_int, buf: *mut c_void, count: usize) -> isize {
8677
return -1;
8778
}
8879

89-
match call_host_function::<Vec<u8>>(
90-
"HostRead",
91-
Some(vec![ParameterValue::ULong(count as u64)]),
92-
ReturnType::VecBytes,
93-
) {
94-
Ok(bytes) => {
95-
let n = bytes.len().min(count);
96-
unsafe {
97-
core::ptr::copy_nonoverlapping(bytes.as_ptr(), buf as *mut u8, n);
98-
}
99-
n as isize
100-
}
101-
Err(_) => {
102-
set_errno(EIO);
103-
-1
104-
}
105-
}
80+
// Return EOF immediately — no host round-trip required.
81+
let _ = (buf, count);
82+
0
10683
}
10784

10885
#[unsafe(no_mangle)]

src/tests/rust_guests/witguest/Cargo.lock

Lines changed: 16 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)