hyperlight_guest/
host_function_call.rs1use alloc::format;
18use alloc::string::ToString;
19use alloc::vec::Vec;
20use core::arch::global_asm;
21
22use hyperlight_common::flatbuffer_wrappers::function_call::{FunctionCall, FunctionCallType};
23use hyperlight_common::flatbuffer_wrappers::function_types::{
24 ParameterValue, ReturnType, ReturnValue,
25};
26use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
27use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result;
28use hyperlight_common::mem::RunMode;
29
30use crate::error::{HyperlightGuestError, Result};
31use crate::host_error::check_for_host_error;
32use crate::host_functions::validate_host_function_call;
33use crate::shared_input_data::try_pop_shared_input_data_into;
34use crate::shared_output_data::push_shared_output_data;
35use crate::{OUTB_PTR, OUTB_PTR_WITH_CONTEXT, P_PEB, RUNNING_MODE};
36
37pub enum OutBAction {
38 Log = 99,
39 CallFunction = 101,
40 Abort = 102,
41}
42
43pub fn get_host_return_value<T: TryFrom<ReturnValue>>() -> Result<T> {
46 let return_value = try_pop_shared_input_data_into::<ReturnValue>()
47 .expect("Unable to deserialize a return value from host");
48 T::try_from(return_value).map_err(|_| {
49 HyperlightGuestError::new(
50 ErrorCode::GuestError,
51 format!(
52 "Host return value was not a {} as expected",
53 core::any::type_name::<T>()
54 ),
55 )
56 })
57}
58
59pub fn call_host_function(
63 function_name: &str,
64 parameters: Option<Vec<ParameterValue>>,
65 return_type: ReturnType,
66) -> Result<()> {
67 let host_function_call = FunctionCall::new(
68 function_name.to_string(),
69 parameters,
70 FunctionCallType::Host,
71 return_type,
72 );
73
74 validate_host_function_call(&host_function_call)?;
75
76 let host_function_call_buffer: Vec<u8> = host_function_call
77 .try_into()
78 .expect("Unable to serialize host function call");
79
80 push_shared_output_data(host_function_call_buffer)?;
81
82 outb(OutBAction::CallFunction as u16, 0);
83
84 Ok(())
85}
86
87pub fn outb(port: u16, value: u8) {
88 unsafe {
89 match RUNNING_MODE {
90 RunMode::Hypervisor => {
91 hloutb(port, value);
92 }
93 RunMode::InProcessLinux | RunMode::InProcessWindows => {
94 if let Some(outb_func) = OUTB_PTR_WITH_CONTEXT {
95 if let Some(peb_ptr) = P_PEB {
96 outb_func((*peb_ptr).pOutbContext, port, value);
97 }
98 } else if let Some(outb_func) = OUTB_PTR {
99 outb_func(port, value);
100 } else {
101 panic!("Tried to call outb without hypervisor and without outb function ptrs");
102 }
103 }
104 _ => {
105 panic!("Tried to call outb in invalid runmode");
106 }
107 }
108
109 check_for_host_error();
110 }
111}
112
113extern "win64" {
114 fn hloutb(port: u16, value: u8);
115}
116
117pub fn print_output_as_guest_function(function_call: &FunctionCall) -> Result<Vec<u8>> {
118 if let ParameterValue::String(message) = function_call.parameters.clone().unwrap()[0].clone() {
119 call_host_function(
120 "HostPrint",
121 Some(Vec::from(&[ParameterValue::String(message.to_string())])),
122 ReturnType::Int,
123 )?;
124 let res_i = get_host_return_value::<i32>()?;
125 Ok(get_flatbuffer_result(res_i))
126 } else {
127 Err(HyperlightGuestError::new(
128 ErrorCode::GuestError,
129 "Wrong Parameters passed to print_output_as_guest_function".to_string(),
130 ))
131 }
132}
133
134global_asm!(
136 ".global hloutb
137 hloutb:
138 xor rax, rax
139 mov al, dl
140 mov dx, cx
141 out dx, al
142 ret"
143);