Skip to content

Commit 42a048d

Browse files
committed
[guest,guest_bin] created GuestHandle and moved entrypoint + guest_logger + exceptions + guest function logic + guest_err
- moved entrypoint to guest_bin library. W/ this, I also moved a lot of things that were only used via the entrypoint: -- IDT/GDT setup for exceptions. -- guest_logger. - w/ the entrypoint fxn from the guest lib having moved, I re-named that module to 'exit' as it still contains stuff for aborting guest execution. I also moved OUT functions there like 'outb' and 'out32'. - a lot of our public functions in the guest lib, like, for example, push_shared_output_data relied on a pub(crate) global (i.e., P_PEB) being set. W/ that only ever being set in the entrypoint and w/ it not being appropriate as pub, I created a GuestHandle struct. This struct houses a *mut HyperlightPEB that operations like push_shared_output_data can leverage. bin-like crates can then create their own GuestHandle globals and use its functionality like self.push_shared_output_data(...). - moved all out guest function defintion, registration and so on to the guest_bin crate. Signed-off-by: danbugs <[email protected]>
1 parent 9698aa4 commit 42a048d

File tree

34 files changed

+755
-690
lines changed

34 files changed

+755
-690
lines changed

Cargo.lock

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

src/hyperlight_guest/Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ printf = [] # compile printf
2020
[dependencies]
2121
anyhow = { version = "1.0.98", default-features = false }
2222
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
23-
buddy_system_allocator = "0.11.0"
2423
hyperlight-common = { workspace = true }
25-
spin = "0.10.0"
26-
log = { version = "0.4", default-features = false }
2724

2825
[build-dependencies]
2926
cc = "1.2"

src/hyperlight_guest/src/entrypoint.rs

Lines changed: 0 additions & 128 deletions
This file was deleted.

src/hyperlight_guest/src/exit.rs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
Copyright 2024 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
use core::arch::asm;
18+
use core::ffi::{c_char, CStr};
19+
20+
use hyperlight_common::outb::OutBAction;
21+
22+
/// Halt the execution of the guest and returns control to the host.
23+
#[inline(never)]
24+
pub fn halt() {
25+
unsafe { asm!("hlt", options(nostack)) }
26+
}
27+
28+
/// Exits the VM with an Abort OUT action and code 0.
29+
#[unsafe(no_mangle)]
30+
pub extern "C" fn abort() -> ! {
31+
abort_with_code(&[0, 0xFF])
32+
}
33+
34+
/// Exits the VM with an Abort OUT action and a specific code.
35+
pub fn abort_with_code(code: &[u8]) -> ! {
36+
outb(OutBAction::Abort as u16, code);
37+
outb(OutBAction::Abort as u16, &[0xFF]); // send abort terminator (if not included in code)
38+
unreachable!()
39+
}
40+
41+
/// Aborts the program with a code and a message.
42+
///
43+
/// # Safety
44+
/// This function is unsafe because it dereferences a raw pointer.
45+
pub unsafe fn abort_with_code_and_message(code: &[u8], message_ptr: *const c_char) -> ! {
46+
unsafe {
47+
// Step 1: Send abort code (typically 1 byte, but `code` allows flexibility)
48+
outb(OutBAction::Abort as u16, code);
49+
50+
// Step 2: Convert the C string to bytes
51+
let message_bytes = CStr::from_ptr(message_ptr).to_bytes(); // excludes null terminator
52+
53+
// Step 3: Send the message itself in chunks
54+
outb(OutBAction::Abort as u16, message_bytes);
55+
56+
// Step 4: Send abort terminator to signal completion (e.g., 0xFF)
57+
outb(OutBAction::Abort as u16, &[0xFF]);
58+
59+
// This function never returns
60+
unreachable!()
61+
}
62+
}
63+
64+
/// OUT bytes to the host through multiple exits.
65+
pub(crate) fn outb(port: u16, data: &[u8]) {
66+
unsafe {
67+
let mut i = 0;
68+
while i < data.len() {
69+
let remaining = data.len() - i;
70+
let chunk_len = remaining.min(3);
71+
let mut chunk = [0u8; 4];
72+
chunk[0] = chunk_len as u8;
73+
chunk[1..1 + chunk_len].copy_from_slice(&data[i..i + chunk_len]);
74+
let val = u32::from_le_bytes(chunk);
75+
out32(port, val);
76+
i += chunk_len;
77+
}
78+
}
79+
}
80+
81+
/// OUT function for sending a 32-bit value to the host.
82+
pub(crate) unsafe fn out32(port: u16, val: u32) {
83+
unsafe {
84+
asm!("out dx, eax", in("dx") port, in("eax") val, options(preserves_flags, nomem, nostack));
85+
}
86+
}
87+
88+
/// Prints a message using `OutBAction::DebugPrint`. It transmits bytes of a message
89+
/// through several VMExists and, with such, it is slower than
90+
/// `print_output_with_host_print`.
91+
///
92+
/// This function should be used in debug mode only. This function does not
93+
/// require memory to be setup to be used.
94+
pub fn debug_print(msg: &str) {
95+
for byte in msg.bytes() {
96+
unsafe {
97+
out32(OutBAction::DebugPrint as u16, byte as u32);
98+
}
99+
}
100+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Copyright 2024 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
use hyperlight_common::mem::HyperlightPEB;
18+
19+
/// A guest handle holds the `HyperlightPEB` and enables the guest to perform
20+
/// operations like:
21+
/// - calling host functions,
22+
/// - accessing shared input and output buffers,
23+
/// - writing errors,
24+
/// - etc.
25+
///
26+
/// Guests are expected to initialize this and store it. For example, you
27+
/// could store it in a global variable.
28+
#[derive(Debug, Clone, Copy)]
29+
pub struct GuestHandle {
30+
peb: Option<*mut HyperlightPEB>,
31+
}
32+
33+
impl GuestHandle {
34+
/// Creates a new uninitialized guest state.
35+
pub const fn new() -> Self {
36+
Self { peb: None }
37+
}
38+
39+
/// Initializes the guest state with a given PEB pointer.
40+
pub fn init(peb: *mut HyperlightPEB) -> Self {
41+
Self { peb: Some(peb) }
42+
}
43+
44+
/// Returns the PEB pointer
45+
pub fn peb(&self) -> Option<*mut HyperlightPEB> {
46+
self.peb
47+
}
48+
}

0 commit comments

Comments
 (0)