Skip to content

Commit 52988bf

Browse files
committed
[common/outb,guest/*,host/{drivers,outb}] added DebugPrint OutBAction
- added action to enable eprinting from an out instruction. - changed out instruciton to output 4 bytes for optimized printing. Signed-off-by: danbugs <[email protected]>
1 parent 8654dc9 commit 52988bf

File tree

12 files changed

+77
-37
lines changed

12 files changed

+77
-37
lines changed

src/hyperlight_common/src/outb.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
/// Supported actions when issuing an OUTB actions by Hyperlight.
2+
/// - Log: for logging,
3+
/// - CallFunction: makes a call to a host function,
4+
/// - Abort: aborts the execution of the guest,
5+
/// - DebugPrint: prints a message to the host
16
pub enum OutBAction {
27
Log = 99,
38
CallFunction = 101,
49
Abort = 102,
10+
DebugPrint = 103,
511
}
612

713
impl TryFrom<u16> for OutBAction {
@@ -11,6 +17,7 @@ impl TryFrom<u16> for OutBAction {
1117
99 => Ok(OutBAction::Log),
1218
101 => Ok(OutBAction::CallFunction),
1319
102 => Ok(OutBAction::Abort),
20+
103 => Ok(OutBAction::DebugPrint),
1421
_ => Err(anyhow::anyhow!("Invalid OutBAction value: {}", val)),
1522
}
1623
}

src/hyperlight_guest/src/entrypoint.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ pub extern "C" fn abort() -> ! {
4848
}
4949

5050
pub fn abort_with_code(code: i32) -> ! {
51-
outb(OutBAction::Abort as u16, code as u8);
51+
let byte = code as u8;
52+
outb(OutBAction::Abort as u16, &[byte]);
5253
unreachable!()
5354
}
5455

@@ -63,7 +64,8 @@ pub unsafe fn abort_with_code_and_message(code: i32, message_ptr: *const c_char)
6364
(*peb_ptr).guestPanicContextData.guestPanicContextDataBuffer as *mut c_char,
6465
CStr::from_ptr(message_ptr).count_bytes() + 1, // +1 for null terminator
6566
);
66-
outb(OutBAction::Abort as u16, code as u8);
67+
let byte = code as u8;
68+
outb(OutBAction::Abort as u16, &[byte]);
6769
unreachable!()
6870
}
6971

@@ -115,7 +117,7 @@ pub extern "win64" fn entrypoint(peb_address: u64, seed: u64, ops: u64, max_log_
115117
RUNNING_MODE = (*peb_ptr).runMode;
116118

117119
OUTB_PTR = {
118-
let outb_ptr: extern "win64" fn(u16, u8) =
120+
let outb_ptr: extern "win64" fn(u16, *const u8, u64) =
119121
core::mem::transmute((*peb_ptr).pOutb);
120122
Some(outb_ptr)
121123
};
@@ -125,8 +127,12 @@ pub extern "win64" fn entrypoint(peb_address: u64, seed: u64, ops: u64, max_log_
125127
}
126128

127129
OUTB_PTR_WITH_CONTEXT = {
128-
let outb_ptr_with_context: extern "win64" fn(*mut c_void, u16, u8) =
129-
core::mem::transmute((*peb_ptr).pOutb);
130+
let outb_ptr_with_context: extern "win64" fn(
131+
*mut c_void,
132+
u16,
133+
*const u8,
134+
u64,
135+
) = core::mem::transmute((*peb_ptr).pOutb);
130136
Some(outb_ptr_with_context)
131137
};
132138
}

src/hyperlight_guest/src/guest_error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub(crate) fn set_error_and_halt(error_code: ErrorCode, message: &str) {
4949

5050
#[no_mangle]
5151
pub(crate) extern "win64" fn set_stack_allocate_error() {
52-
outb(OutBAction::Abort as u16, ErrorCode::StackOverflow as u8);
52+
outb(OutBAction::Abort as u16, &[ErrorCode::StackOverflow as u8]);
5353
}
5454

5555
#[no_mangle]

src/hyperlight_guest/src/host_function_call.rs

+32-14
Original file line numberDiff line numberDiff line change
@@ -70,24 +70,40 @@ pub fn call_host_function(
7070

7171
push_shared_output_data(host_function_call_buffer)?;
7272

73-
outb(OutBAction::CallFunction as u16, 0);
73+
outb(OutBAction::CallFunction as u16, &[0]);
7474

7575
Ok(())
7676
}
7777

78-
pub fn outb(port: u16, value: u8) {
78+
pub fn outb(port: u16, data: &[u8]) {
7979
unsafe {
8080
match RUNNING_MODE {
8181
RunMode::Hypervisor => {
82-
hloutb(port, value);
82+
for chunk in data.chunks(4) {
83+
let val = match chunk {
84+
[a, b, c, d] => u32::from_le_bytes([*a, *b, *c, *d]),
85+
[a, b, c] => u32::from_le_bytes([*a, *b, *c, 0]),
86+
[a, b] => u32::from_le_bytes([*a, *b, 0, 0]),
87+
[a] => u32::from_le_bytes([*a, 0, 0, 0]),
88+
[] => break,
89+
_ => unreachable!(),
90+
};
91+
92+
hloutd(val, port);
93+
}
8394
}
8495
RunMode::InProcessLinux | RunMode::InProcessWindows => {
8596
if let Some(outb_func) = OUTB_PTR_WITH_CONTEXT {
8697
if let Some(peb_ptr) = P_PEB {
87-
outb_func((*peb_ptr).pOutbContext, port, value);
98+
outb_func(
99+
(*peb_ptr).pOutbContext,
100+
port,
101+
data.as_ptr(),
102+
data.len() as u64,
103+
);
88104
}
89105
} else if let Some(outb_func) = OUTB_PTR {
90-
outb_func(port, value);
106+
outb_func(port, data.as_ptr(), data.len() as u64);
91107
} else {
92108
panic!("Tried to call outb without hypervisor and without outb function ptrs");
93109
}
@@ -100,7 +116,7 @@ pub fn outb(port: u16, value: u8) {
100116
}
101117

102118
extern "win64" {
103-
fn hloutb(port: u16, value: u8);
119+
fn hloutd(value: u32, port: u16);
104120
}
105121

106122
pub fn print_output_as_guest_function(function_call: &FunctionCall) -> Result<Vec<u8>> {
@@ -120,13 +136,15 @@ pub fn print_output_as_guest_function(function_call: &FunctionCall) -> Result<Ve
120136
}
121137
}
122138

123-
// port: RCX(cx), value: RDX(dl)
139+
pub fn debug_print(msg: &str) {
140+
outb(OutBAction::DebugPrint as u16, msg.as_bytes());
141+
}
142+
124143
global_asm!(
125-
".global hloutb
126-
hloutb:
127-
xor rax, rax
128-
mov al, dl
129-
mov dx, cx
130-
out dx, al
131-
ret"
144+
".global hloutd
145+
hloutd:
146+
mov eax, ecx
147+
mov dx, dx
148+
out dx, eax
149+
ret"
132150
);

src/hyperlight_guest/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
8181
(*peb_ptr).guestPanicContextData.guestPanicContextDataSize as usize,
8282
);
8383
}
84-
outb(OutBAction::Abort as u16, ErrorCode::UnknownError as u8);
84+
outb(OutBAction::Abort as u16, &[ErrorCode::UnknownError as u8]);
8585
unsafe { unreachable_unchecked() }
8686
}
8787

@@ -97,9 +97,9 @@ pub(crate) static mut P_PEB: Option<*mut HyperlightPEB> = None;
9797
pub static mut MIN_STACK_ADDRESS: u64 = 0;
9898

9999
pub static mut OS_PAGE_SIZE: u32 = 0;
100-
pub(crate) static mut OUTB_PTR: Option<extern "win64" fn(u16, u8)> = None;
100+
pub(crate) static mut OUTB_PTR: Option<extern "win64" fn(u16, *const u8, u64)> = None;
101101
pub(crate) static mut OUTB_PTR_WITH_CONTEXT: Option<
102-
extern "win64" fn(*mut core::ffi::c_void, u16, u8),
102+
extern "win64" fn(*mut core::ffi::c_void, u16, *const u8, u64),
103103
> = None;
104104
pub static mut RUNNING_MODE: RunMode = RunMode::None;
105105

src/hyperlight_guest/src/logging.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,5 @@ pub fn log_message(
5757
line: u32,
5858
) {
5959
write_log_data(log_level, message, source, caller, source_file, line);
60-
outb(OutBAction::Log as u16, 0);
60+
outb(OutBAction::Log as u16, &[0]);
6161
}

src/hyperlight_host/src/hypervisor/handlers.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::{new_error, Result};
2525
/// has initiated an outb operation.
2626
pub trait OutBHandlerCaller: Sync + Send {
2727
/// Function that gets called when an outb operation has occurred.
28-
fn call(&mut self, port: u16, payload: u64) -> Result<()>;
28+
fn call(&mut self, port: u16, payload: Vec<u8>) -> Result<()>;
2929
}
3030

3131
/// A convenient type representing a common way `OutBHandler` implementations
@@ -36,7 +36,7 @@ pub trait OutBHandlerCaller: Sync + Send {
3636
/// a &mut self).
3737
pub type OutBHandlerWrapper = Arc<Mutex<dyn OutBHandlerCaller>>;
3838

39-
pub(crate) type OutBHandlerFunction = Box<dyn FnMut(u16, u64) -> Result<()> + Send>;
39+
pub(crate) type OutBHandlerFunction = Box<dyn FnMut(u16, Vec<u8>) -> Result<()> + Send>;
4040

4141
/// A `OutBHandler` implementation using a `OutBHandlerFunction`
4242
///
@@ -52,7 +52,7 @@ impl From<OutBHandlerFunction> for OutBHandler {
5252

5353
impl OutBHandlerCaller for OutBHandler {
5454
#[instrument(err(Debug), skip_all, parent = Span::current(), level= "Trace")]
55-
fn call(&mut self, port: u16, payload: u64) -> Result<()> {
55+
fn call(&mut self, port: u16, payload: Vec<u8>) -> Result<()> {
5656
let mut func = self
5757
.0
5858
.try_lock()

src/hyperlight_host/src/hypervisor/hyperv_linux.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -542,11 +542,10 @@ impl Hypervisor for HypervLinuxDriver {
542542
instruction_length: u64,
543543
outb_handle_fn: OutBHandlerWrapper,
544544
) -> Result<()> {
545-
let payload = data[..8].try_into()?;
546545
outb_handle_fn
547546
.try_lock()
548547
.map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
549-
.call(port, u64::from_le_bytes(payload))?;
548+
.call(port, data)?;
550549

551550
// update rip
552551
self.vcpu_fd.set_reg(&[hv_register_assoc {

src/hyperlight_host/src/hypervisor/hyperv_windows.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,10 @@ impl Hypervisor for HypervWindowsDriver {
390390
instruction_length: u64,
391391
outb_handle_fn: OutBHandlerWrapper,
392392
) -> Result<()> {
393-
let payload = data[..8].try_into()?;
394393
outb_handle_fn
395394
.try_lock()
396395
.map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
397-
.call(port, u64::from_le_bytes(payload))?;
396+
.call(port, payload)?;
398397

399398
let mut regs = self.processor.get_regs()?;
400399
regs.rip = rip + instruction_length;

src/hyperlight_host/src/hypervisor/kvm.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -497,11 +497,10 @@ impl Hypervisor for KVMDriver {
497497
if data.is_empty() {
498498
log_then_return!("no data was given in IO interrupt");
499499
} else {
500-
let payload_u64 = u64::from(data[0]);
501500
outb_handle_fn
502501
.try_lock()
503502
.map_err(|e| new_error!("Error locking at {}:{}: {}", file!(), line!(), e))?
504-
.call(port, payload_u64)?;
503+
.call(port, data)?;
505504
}
506505

507506
Ok(())
@@ -665,7 +664,7 @@ mod tests {
665664
}
666665

667666
let outb_handler: Arc<Mutex<OutBHandler>> = {
668-
let func: Box<dyn FnMut(u16, u64) -> Result<()> + Send> =
667+
let func: Box<dyn FnMut(u16, Vec<u8>) -> Result<()> + Send> =
669668
Box::new(|_, _| -> Result<()> { Ok(()) });
670669
Arc::new(Mutex::new(OutBHandler::from(func)))
671670
};

src/hyperlight_host/src/sandbox/leaked_outb.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,19 @@ use crate::mem::shared_mem::GuestSharedMemory;
2929
///
3030
/// NOTE: This is not part of the C Hyperlight API , it is intended only to be
3131
/// called in proc through a pointer passed to the guest.
32-
extern "win64" fn call_outb(ptr: *mut Arc<Mutex<dyn OutBHandlerCaller>>, port: u16, data: u64) {
32+
extern "win64" fn call_outb(
33+
ptr: *mut Arc<Mutex<dyn OutBHandlerCaller>>,
34+
port: u16,
35+
data_ptr: *const u8,
36+
data_len: u64,
37+
) {
3338
let outb_handlercaller = unsafe { Box::from_raw(ptr) };
39+
let slice = unsafe { std::slice::from_raw_parts(data_ptr, data_len as usize) };
3440
let res = outb_handlercaller
3541
.try_lock()
3642
.map_err(|_| crate::new_error!("Error locking"))
3743
.unwrap()
38-
.call(port, data);
44+
.call(port, slice.to_vec());
3945
// TODO, handle the case correctly when res is an error
4046
assert!(
4147
res.is_ok(),

src/hyperlight_host/src/sandbox/outb.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn handle_outb_impl(
9999
mem_mgr: &mut MemMgrWrapper<HostSharedMemory>,
100100
host_funcs: Arc<Mutex<HostFuncsWrapper>>,
101101
port: u16,
102-
byte: u64,
102+
data: Vec<u8>,
103103
) -> Result<()> {
104104
match port.try_into()? {
105105
OutBAction::Log => outb_log(mem_mgr.as_mut()),
@@ -118,6 +118,7 @@ fn handle_outb_impl(
118118
Ok(())
119119
}
120120
OutBAction::Abort => {
121+
let byte = u64::from(data[0]);
121122
let guest_error = ErrorCode::from(byte);
122123
let panic_context = mem_mgr.as_mut().read_guest_panic_context_data()?;
123124
// trim off trailing \0 bytes if they exist
@@ -135,6 +136,11 @@ fn handle_outb_impl(
135136
)),
136137
}
137138
}
139+
OutBAction::DebugPrint => {
140+
let s = String::from_utf8_lossy(&data);
141+
eprint!("{}", s);
142+
Ok(())
143+
}
138144
}
139145
}
140146

0 commit comments

Comments
 (0)