hyperlight_guest/
host_function_call.rs1use alloc::string::ToString;
18use alloc::vec::Vec;
19use core::arch::global_asm;
20
21use hyperlight_common::flatbuffer_wrappers::function_call::{FunctionCall, FunctionCallType};
22use hyperlight_common::flatbuffer_wrappers::function_types::{
23 ParameterValue, ReturnType, ReturnValue,
24};
25use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
26use hyperlight_common::flatbuffer_wrappers::util::get_flatbuffer_result_from_int;
27use hyperlight_common::mem::RunMode;
28
29use crate::error::{HyperlightGuestError, Result};
30use crate::host_error::check_for_host_error;
31use crate::host_functions::validate_host_function_call;
32use crate::shared_input_data::try_pop_shared_input_data_into;
33use crate::shared_output_data::push_shared_output_data;
34use crate::{OUTB_PTR, OUTB_PTR_WITH_CONTEXT, P_PEB, RUNNING_MODE};
35
36pub enum OutBAction {
37 Log = 99,
38 CallFunction = 101,
39 Abort = 102,
40}
41
42pub fn get_host_value_return_as_void() -> Result<()> {
43 let return_value = try_pop_shared_input_data_into::<ReturnValue>()
44 .expect("Unable to deserialize a return value from host");
45 if let ReturnValue::Void = return_value {
46 Ok(())
47 } else {
48 Err(HyperlightGuestError::new(
49 ErrorCode::GuestError,
50 "Host return value was not void as expected".to_string(),
51 ))
52 }
53}
54
55pub fn get_host_value_return_as_int() -> Result<i32> {
56 let return_value = try_pop_shared_input_data_into::<ReturnValue>()
57 .expect("Unable to deserialize return value from host");
58
59 if let ReturnValue::Int(i) = return_value {
61 Ok(i)
62 } else {
63 Err(HyperlightGuestError::new(
64 ErrorCode::GuestError,
65 "Host return value was not an int as expected".to_string(),
66 ))
67 }
68}
69
70pub fn get_host_value_return_as_uint() -> Result<u32> {
71 let return_value = try_pop_shared_input_data_into::<ReturnValue>()
72 .expect("Unable to deserialize return value from host");
73
74 if let ReturnValue::UInt(ui) = return_value {
76 Ok(ui)
77 } else {
78 Err(HyperlightGuestError::new(
79 ErrorCode::GuestError,
80 "Host return value was not a uint as expected".to_string(),
81 ))
82 }
83}
84
85pub fn get_host_value_return_as_long() -> Result<i64> {
86 let return_value = try_pop_shared_input_data_into::<ReturnValue>()
87 .expect("Unable to deserialize return value from host");
88
89 if let ReturnValue::Long(l) = return_value {
91 Ok(l)
92 } else {
93 Err(HyperlightGuestError::new(
94 ErrorCode::GuestError,
95 "Host return value was not a long as expected".to_string(),
96 ))
97 }
98}
99
100pub fn get_host_value_return_as_ulong() -> Result<u64> {
101 let return_value = try_pop_shared_input_data_into::<ReturnValue>()
102 .expect("Unable to deserialize return value from host");
103
104 if let ReturnValue::ULong(ul) = return_value {
106 Ok(ul)
107 } else {
108 Err(HyperlightGuestError::new(
109 ErrorCode::GuestError,
110 "Host return value was not a ulong as expected".to_string(),
111 ))
112 }
113}
114
115pub fn get_host_value_return_as_vecbytes() -> Result<Vec<u8>> {
118 let return_value = try_pop_shared_input_data_into::<ReturnValue>()
119 .expect("Unable to deserialize return value from host");
120
121 if let ReturnValue::VecBytes(v) = return_value {
123 Ok(v)
124 } else {
125 Err(HyperlightGuestError::new(
126 ErrorCode::GuestError,
127 "Host return value was not an VecBytes as expected".to_string(),
128 ))
129 }
130}
131
132pub fn call_host_function(
136 function_name: &str,
137 parameters: Option<Vec<ParameterValue>>,
138 return_type: ReturnType,
139) -> Result<()> {
140 let host_function_call = FunctionCall::new(
141 function_name.to_string(),
142 parameters,
143 FunctionCallType::Host,
144 return_type,
145 );
146
147 validate_host_function_call(&host_function_call)?;
148
149 let host_function_call_buffer: Vec<u8> = host_function_call
150 .try_into()
151 .expect("Unable to serialize host function call");
152
153 push_shared_output_data(host_function_call_buffer)?;
154
155 outb(OutBAction::CallFunction as u16, 0);
156
157 Ok(())
158}
159
160pub fn outb(port: u16, value: u8) {
161 unsafe {
162 match RUNNING_MODE {
163 RunMode::Hypervisor => {
164 hloutb(port, value);
165 }
166 RunMode::InProcessLinux | RunMode::InProcessWindows => {
167 if let Some(outb_func) = OUTB_PTR_WITH_CONTEXT {
168 if let Some(peb_ptr) = P_PEB {
169 outb_func((*peb_ptr).pOutbContext, port, value);
170 }
171 } else if let Some(outb_func) = OUTB_PTR {
172 outb_func(port, value);
173 } else {
174 panic!("Tried to call outb without hypervisor and without outb function ptrs");
175 }
176 }
177 _ => {
178 panic!("Tried to call outb in invalid runmode");
179 }
180 }
181
182 check_for_host_error();
183 }
184}
185
186extern "win64" {
187 fn hloutb(port: u16, value: u8);
188}
189
190pub fn print_output_as_guest_function(function_call: &FunctionCall) -> Result<Vec<u8>> {
191 if let ParameterValue::String(message) = function_call.parameters.clone().unwrap()[0].clone() {
192 call_host_function(
193 "HostPrint",
194 Some(Vec::from(&[ParameterValue::String(message.to_string())])),
195 ReturnType::Int,
196 )?;
197 let res_i = get_host_value_return_as_int()?;
198 Ok(get_flatbuffer_result_from_int(res_i))
199 } else {
200 Err(HyperlightGuestError::new(
201 ErrorCode::GuestError,
202 "Wrong Parameters passed to print_output_as_guest_function".to_string(),
203 ))
204 }
205}
206
207global_asm!(
209 ".global hloutb
210 hloutb:
211 xor rax, rax
212 mov al, dl
213 mov dx, cx
214 out dx, al
215 ret"
216);