hermit/syscalls/interfaces/
uhyve.rs1use core::ptr;
2
3use memory_addresses::VirtAddr;
4use uhyve_interface::parameters::{ExitParams, SerialWriteBufferParams};
5use uhyve_interface::{Hypercall, HypercallAddress};
6
7use crate::arch;
8use crate::arch::mm::paging::{self, virtual_to_physical};
9use crate::syscalls::interfaces::SyscallInterface;
10
11#[inline]
13#[cfg_attr(target_arch = "riscv64", expect(dead_code))]
14pub(crate) fn serial_buf_hypercall(buf: &[u8]) {
15 let p = SerialWriteBufferParams {
16 buf: virtual_to_physical(VirtAddr::from_ptr(core::ptr::from_ref::<[u8]>(buf))).unwrap(),
17 len: buf.len(),
18 };
19 uhyve_hypercall(Hypercall::SerialWriteBuffer(&p));
20}
21
22#[inline]
24fn data_addr<T>(data: &T) -> u64 {
25 paging::virtual_to_physical(VirtAddr::from_ptr(ptr::from_ref(data)))
26 .unwrap()
27 .as_u64()
28}
29
30#[inline]
32fn hypercall_data(hypercall: &Hypercall<'_>) -> u64 {
33 match hypercall {
34 Hypercall::Cmdsize(data) => data_addr(*data),
35 Hypercall::Cmdval(data) => data_addr(*data),
36 Hypercall::Exit(data) => data_addr(*data),
37 Hypercall::FileClose(data) => data_addr(*data),
38 Hypercall::FileLseek(data) => data_addr(*data),
39 Hypercall::FileOpen(data) => data_addr(*data),
40 Hypercall::FileRead(data) => data_addr(*data),
41 Hypercall::FileUnlink(data) => data_addr(*data),
42 Hypercall::FileWrite(data) => data_addr(*data),
43 Hypercall::SerialWriteBuffer(data) => data_addr(*data),
44 Hypercall::SerialWriteByte(byte) => u64::from(*byte),
45 h => todo!("unimplemented hypercall {h:?}"),
46 }
47}
48
49#[inline]
51#[allow(unused_variables)] pub(crate) fn uhyve_hypercall(hypercall: Hypercall<'_>) {
53 let ptr = HypercallAddress::from(&hypercall) as u16;
54 let data = hypercall_data(&hypercall);
55
56 #[cfg(target_arch = "x86_64")]
57 unsafe {
58 use x86_64::instructions::port::Port;
59
60 let data =
61 u32::try_from(data).expect("Hypercall data must lie in the first 4GiB of memory");
62 Port::new(ptr).write(data);
63 }
64
65 #[cfg(target_arch = "aarch64")]
66 unsafe {
67 use core::arch::asm;
68 asm!(
69 "str x8, [{ptr}]",
70 ptr = in(reg) u64::from(ptr),
71 in("x8") data,
72 options(nostack),
73 );
74 }
75
76 #[cfg(target_arch = "riscv64")]
77 todo!()
78}
79
80pub struct Uhyve;
81
82impl SyscallInterface for Uhyve {
83 fn shutdown(&self, error_code: i32) -> ! {
84 let sysexit = ExitParams { arg: error_code };
85 uhyve_hypercall(Hypercall::Exit(&sysexit));
86
87 loop {
88 arch::processor::halt();
89 }
90 }
91}