Skip to content

Commit e9f5ace

Browse files
committed
Create an fmt::Write implementation that writes formatted string to port-based io directly to stream
error messages to the host and avoid needing a fixed-size buffer in the panic handler. Signed-off-by: adamperlin <adamp@nanosoft.com>
1 parent cf5efdb commit e9f5ace

File tree

2 files changed

+36
-23
lines changed

2 files changed

+36
-23
lines changed

src/hyperlight_guest/src/exit.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ pub unsafe fn abort_with_code_and_message(code: &[u8], message_ptr: *const c_cha
6767
}
6868
}
6969

70+
/// This function exists to give the guest more manual control
71+
/// over the abort sequence. For example, in the panic handler,
72+
/// we have a message of unknown length that we want to stream
73+
/// to the host, which requires sending the message in chunks
74+
pub unsafe fn write_abort(code: &[u8]) {
75+
outb(OutBAction::Abort as u16, code);
76+
}
77+
7078
/// OUT bytes to the host through multiple exits.
7179
#[hyperlight_guest_tracing::trace_function]
7280
pub(crate) fn outb(port: u16, data: &[u8]) {

src/hyperlight_guest_bin/src/lib.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ limitations under the License.
1818
// === Dependencies ===
1919
extern crate alloc;
2020

21-
use core::ffi::CStr;
2221
use core::fmt::Write;
2322

2423
use buddy_system_allocator::LockedHeap;
@@ -27,12 +26,11 @@ use exceptions::{gdt::load_gdt, idtr::load_idt};
2726
use guest_function::call::dispatch_function;
2827
use guest_function::register::GuestFunctionRegister;
2928
use guest_logger::init_logger;
30-
use heapless::String;
3129
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
3230
use hyperlight_common::mem::HyperlightPEB;
3331
#[cfg(feature = "mem_profile")]
3432
use hyperlight_common::outb::OutBAction;
35-
use hyperlight_guest::exit::{abort_with_code_and_message, halt};
33+
use hyperlight_guest::exit::{halt, write_abort};
3634
use hyperlight_guest::guest_handle::handle::GuestHandle;
3735
use hyperlight_guest_tracing::{trace, trace_function};
3836
use log::LevelFilter;
@@ -144,35 +142,42 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
144142
_panic_handler(info)
145143
}
146144

147-
#[inline(always)]
148-
fn _panic_handler(info: &core::panic::PanicInfo) -> ! {
149-
// stack allocate a 512-byte message buffer.
150-
let mut panic_buf = String::<512>::new();
151-
let write_res = write!(panic_buf, "{}\0", info);
152-
if write_res.is_err() {
145+
/// A writer that sends all output to the hyperlight host
146+
/// using output ports. This allows us to not impose a
147+
/// buffering limit on error message size on the guest end,
148+
/// though one exists for the host.
149+
struct HyperlightAbortWriter;
150+
impl core::fmt::Write for HyperlightAbortWriter {
151+
fn write_str(&mut self, s: &str) -> core::fmt::Result {
153152
unsafe {
154-
abort_with_code_and_message(
155-
&[ErrorCode::UnknownError as u8],
156-
c"panic: message format failed (limit: 512 bytes)".as_ptr(),
157-
)
153+
write_abort(s.as_bytes());
158154
}
155+
Ok(())
159156
}
157+
}
160158

161-
let c_str_res = CStr::from_bytes_with_nul(panic_buf.as_bytes());
162-
if c_str_res.is_err() {
159+
#[inline(always)]
160+
fn _panic_handler(info: &core::panic::PanicInfo) -> ! {
161+
let mut w = HyperlightAbortWriter;
162+
163+
// begin abort sequence by writing the error code
164+
unsafe {
165+
write_abort(
166+
&[ErrorCode::UnknownError as u8]);
167+
}
168+
169+
let write_res = write!(w, "{}", info);
170+
if write_res.is_err() {
163171
unsafe {
164-
abort_with_code_and_message(
165-
&[ErrorCode::UnknownError as u8],
166-
c"panic: failed to convert to CString".as_ptr(),
167-
)
172+
write_abort("panic: message format failed".as_bytes());
168173
}
169174
}
170175

176+
// write abort terminator to finish the abort
177+
// and signal to the host that the message can now be read
171178
unsafe {
172-
abort_with_code_and_message(
173-
&[ErrorCode::UnknownError as u8],
174-
c_str_res.unwrap().as_ptr(),
175-
)
179+
write_abort(&[0xFF]);
180+
unreachable!();
176181
}
177182
}
178183

0 commit comments

Comments
 (0)