From 239d6678c19f8a89e8735397a34956ba2449b606 Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Tue, 12 Mar 2024 15:28:06 +0100 Subject: [PATCH 1/7] moved generalized init_guest_mem to crate::arch --- src/arch/aarch64/mod.rs | 72 ++++++++++++++++++++++++++++++++++++ src/arch/x86_64/mod.rs | 5 +++ src/macos/aarch64/uhyve.rs | 76 -------------------------------------- src/vm.rs | 4 +- 4 files changed, 78 insertions(+), 79 deletions(-) diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index cd087dab..362c0b5a 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -58,3 +58,75 @@ bitflags! { const D_BIT = 0x00000200; } } + +pub fn init_guest_mem(mem: &mut [u8]) { + let mem_addr = std::ptr::addr_of_mut!(mem[0]); + + assert(mem.len() >= BOOT_PGT + 512 * sizeof::()); + let pgt_slice = unsafe { + std::slice::from_raw_parts_mut( + mem_addr.offset(BOOT_PGT.try_into().unwrap()) as *mut u64, + 512, + ) + }; + pgt_slice.fill(0); + pgt_slice[0] = BOOT_PGT + 0x1000 + PT_PT; + pgt_slice[511] = BOOT_PGT + PT_PT + PT_SELF; + + assert(mem.len() >= BOOT_PGT + 0x1000 + 512 * sizeof::()); + let pgt_slice = unsafe { + std::slice::from_raw_parts_mut( + mem_addr.offset((BOOT_PGT + 0x1000).try_into().unwrap()) as *mut u64, + 512, + ) + }; + pgt_slice.fill(0); + pgt_slice[0] = BOOT_PGT + 0x2000 + PT_PT; + + assert(mem.len() >= BOOT_PGT + 0x2000 + 512 * sizeof::()); + let pgt_slice = unsafe { + std::slice::from_raw_parts_mut( + mem_addr.offset((BOOT_PGT + 0x2000).try_into().unwrap()) as *mut u64, + 512, + ) + }; + pgt_slice.fill(0); + pgt_slice[0] = BOOT_PGT + 0x3000 + PT_PT; + pgt_slice[1] = BOOT_PGT + 0x4000 + PT_PT; + pgt_slice[2] = BOOT_PGT + 0x5000 + PT_PT; + + assert(mem.len() >= BOOT_PGT + 0x3000 + 512 * sizeof::()); + let pgt_slice = unsafe { + std::slice::from_raw_parts_mut( + mem_addr.offset((BOOT_PGT + 0x3000).try_into().unwrap()) as *mut u64, + 512, + ) + }; + pgt_slice.fill(0); + // map uhyve ports into the virtual address space + pgt_slice[0] = PT_MEM_CD; + // map BootInfo into the virtual address space + pgt_slice[BOOT_INFO_ADDR as usize / PAGE_SIZE] = BOOT_INFO_ADDR + PT_MEM; + + assert(mem.len() >= BOOT_PGT + 0x4000 + 512 * sizeof::()); + let pgt_slice = unsafe { + std::slice::from_raw_parts_mut( + mem_addr.offset((BOOT_PGT + 0x4000).try_into().unwrap()) as *mut u64, + 512, + ) + }; + for (idx, i) in pgt_slice.iter_mut().enumerate() { + *i = 0x200000u64 + (idx * PAGE_SIZE) as u64 + PT_MEM; + } + + assert(mem.len() >= BOOT_PGT + 0x5000 + 512 * sizeof::()); + let pgt_slice = unsafe { + std::slice::from_raw_parts_mut( + mem_addr.offset((BOOT_PGT + 0x5000).try_into().unwrap()) as *mut u64, + 512, + ) + }; + for (idx, i) in pgt_slice.iter_mut().enumerate() { + *i = 0x400000u64 + (idx * PAGE_SIZE) as u64 + PT_MEM; + } +} diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 4468ff93..a615d161 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -237,6 +237,11 @@ pub fn virt_to_phys( Ok(entry.addr() + (addr.as_u64() & !((!0u64) << PAGE_BITS))) } +pub fn init_guest_mem(mem: &mut [u8]) { + // TODO: we should maybe return an error on failure (e.g., the memory is too small) + initialize_pagetables(mem); +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/macos/aarch64/uhyve.rs b/src/macos/aarch64/uhyve.rs index 554a5252..f35fd4f8 100644 --- a/src/macos/aarch64/uhyve.rs +++ b/src/macos/aarch64/uhyve.rs @@ -159,82 +159,6 @@ impl Vm for Uhyve { fn set_boot_info(&mut self, header: *const RawBootInfo) { self.boot_info = header; } - - fn init_guest_mem(&mut self) { - debug!("Initialize guest memory"); - - let (mem_addr, _) = self.guest_mem(); - - let pgt_slice = unsafe { - std::slice::from_raw_parts_mut( - mem_addr.offset(BOOT_PGT.try_into().unwrap()) as *mut u64, - 512, - ) - }; - for i in pgt_slice.iter_mut() { - *i = 0; - } - pgt_slice[0] = BOOT_PGT + 0x1000 + PT_PT; - pgt_slice[511] = BOOT_PGT + PT_PT + PT_SELF; - - let pgt_slice = unsafe { - std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x1000).try_into().unwrap()) as *mut u64, - 512, - ) - }; - for i in pgt_slice.iter_mut() { - *i = 0; - } - pgt_slice[0] = BOOT_PGT + 0x2000 + PT_PT; - - let pgt_slice = unsafe { - std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x2000).try_into().unwrap()) as *mut u64, - 512, - ) - }; - for i in pgt_slice.iter_mut() { - *i = 0; - } - pgt_slice[0] = BOOT_PGT + 0x3000 + PT_PT; - pgt_slice[1] = BOOT_PGT + 0x4000 + PT_PT; - pgt_slice[2] = BOOT_PGT + 0x5000 + PT_PT; - - let pgt_slice = unsafe { - std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x3000).try_into().unwrap()) as *mut u64, - 512, - ) - }; - for i in pgt_slice.iter_mut() { - *i = 0; - } - // map uhyve ports into the virtual address space - pgt_slice[0] = PT_MEM_CD; - // map BootInfo into the virtual address space - pgt_slice[BOOT_INFO_ADDR as usize / PAGE_SIZE] = BOOT_INFO_ADDR + PT_MEM; - - let pgt_slice = unsafe { - std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x4000).try_into().unwrap()) as *mut u64, - 512, - ) - }; - for (idx, i) in pgt_slice.iter_mut().enumerate() { - *i = 0x200000u64 + (idx * PAGE_SIZE) as u64 + PT_MEM; - } - - let pgt_slice = unsafe { - std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x5000).try_into().unwrap()) as *mut u64, - 512, - ) - }; - for (idx, i) in pgt_slice.iter_mut().enumerate() { - *i = 0x400000u64 + (idx * PAGE_SIZE) as u64 + PT_MEM; - } - } } impl Drop for Uhyve { diff --git a/src/vm.rs b/src/vm.rs index b3536877..a01010bf 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -168,9 +168,7 @@ impl UhyveVm { /// Initialize the page tables for the guest fn init_guest_mem(&mut self) { debug!("Initialize guest memory"); - - #[cfg(target_arch = "x86_64")] - crate::x86_64::initialize_pagetables( + crate::arch::init_guest_mem( unsafe { self.mem.as_slice_mut() } // slice only lives during this fn call .try_into() .expect("Guest memory is not large enough for pagetables"), From d8b6c3d53e4aee7721823e135d8bf0883fffdd04 Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Tue, 12 Mar 2024 15:28:06 +0100 Subject: [PATCH 2/7] Moved some paging stuff (error) into non-arch module --- src/arch/x86_64/mod.rs | 8 +------- src/lib.rs | 1 + src/paging.rs | 8 ++++++++ 3 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 src/paging.rs diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index a615d161..20f70853 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -18,7 +18,7 @@ use x86_64::{ PhysAddr, }; -use crate::{consts::*, mem::MmapMemory}; +use crate::{consts::*, mem::MmapMemory, paging::PagetableError}; pub const RAM_START: GuestPhysAddr = GuestPhysAddr::new(0x00); const MHZ_TO_HZ: u64 = 1000000; @@ -192,12 +192,6 @@ pub fn initialize_pagetables(mem: &mut [u8]) { } } -#[derive(Error, Debug)] -pub enum PagetableError { - #[error("The accessed virtual address is not mapped")] - InvalidAddress, -} - /// Converts a virtual address in the guest to a physical address in the guest pub fn virt_to_phys( addr: GuestVirtAddr, diff --git a/src/lib.rs b/src/lib.rs index 83e1eb1a..7c2f2177 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,6 +21,7 @@ pub mod macos; pub use macos as os; mod hypercall; pub mod mem; +pub mod paging; pub mod params; #[cfg(target_os = "linux")] pub mod shared_queue; diff --git a/src/paging.rs b/src/paging.rs new file mode 100644 index 00000000..a8d27925 --- /dev/null +++ b/src/paging.rs @@ -0,0 +1,8 @@ +//! General paging related code +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum PagetableError { + #[error("The accessed virtual address is not mapped")] + InvalidAddress, +} From f5ae621e16c71921d222a797dfc7f2abd33274fb Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Tue, 12 Mar 2024 15:28:06 +0100 Subject: [PATCH 3/7] Use GuestPhysAddr and GuestVirtAddr everywhere, also on aarch64 --- Cargo.lock | 26 +++++++++++++++++++++ src/arch/aarch64/mod.rs | 46 +++++++++++++++++++------------------- src/consts.rs | 14 ++++++------ src/macos/aarch64/vcpu.rs | 5 +++-- uhyve-interface/Cargo.toml | 6 ++++- uhyve-interface/src/lib.rs | 5 +++++ 6 files changed, 69 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ee369a1..4ead1076 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,25 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aarch64" +version = "0.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adf345d8b4e2861016511db094993ee8a9f74195f55ccf62d1305d35ab91bfa" +dependencies = [ + "aarch64-cpu", + "tock-registers", +] + +[[package]] +name = "aarch64-cpu" +version = "9.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" +dependencies = [ + "tock-registers", +] + [[package]] name = "ahash" version = "0.7.7" @@ -1413,6 +1432,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tock-registers" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" + [[package]] name = "toml" version = "0.5.11" @@ -1471,6 +1496,7 @@ dependencies = [ name = "uhyve-interface" version = "0.1.0" dependencies = [ + "aarch64", "log", "num_enum", "x86_64", diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 362c0b5a..cc203067 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -1,6 +1,9 @@ +use crate::consts::{BOOT_INFO_ADDR, BOOT_PGT, PAGE_SIZE}; use bitflags::bitflags; +use std::mem::size_of; +use uhyve_interface::GuestPhysAddr; -pub const RAM_START: u64 = 0x00; +pub const RAM_START: GuestPhysAddr = GuestPhysAddr::new(0x00); pub const PT_DEVICE: u64 = 0x707; pub const PT_PT: u64 = 0x713; @@ -62,43 +65,40 @@ bitflags! { pub fn init_guest_mem(mem: &mut [u8]) { let mem_addr = std::ptr::addr_of_mut!(mem[0]); - assert(mem.len() >= BOOT_PGT + 512 * sizeof::()); + assert!(mem.len() >= BOOT_PGT.as_u64() as usize + 512 * size_of::()); let pgt_slice = unsafe { - std::slice::from_raw_parts_mut( - mem_addr.offset(BOOT_PGT.try_into().unwrap()) as *mut u64, - 512, - ) + std::slice::from_raw_parts_mut(mem_addr.offset(BOOT_PGT.as_u64() as isize) as *mut u64, 512) }; pgt_slice.fill(0); - pgt_slice[0] = BOOT_PGT + 0x1000 + PT_PT; - pgt_slice[511] = BOOT_PGT + PT_PT + PT_SELF; + pgt_slice[0] = BOOT_PGT.as_u64() + 0x1000 + PT_PT; + pgt_slice[511] = BOOT_PGT.as_u64() + PT_PT + PT_SELF; - assert(mem.len() >= BOOT_PGT + 0x1000 + 512 * sizeof::()); + assert!(mem.len() >= BOOT_PGT.as_u64() as usize + 0x1000 + 512 * size_of::()); let pgt_slice = unsafe { std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x1000).try_into().unwrap()) as *mut u64, + mem_addr.offset(BOOT_PGT.as_u64() as isize + 0x1000) as *mut u64, 512, ) }; pgt_slice.fill(0); - pgt_slice[0] = BOOT_PGT + 0x2000 + PT_PT; + pgt_slice[0] = BOOT_PGT.as_u64() + 0x2000 + PT_PT; - assert(mem.len() >= BOOT_PGT + 0x2000 + 512 * sizeof::()); + assert!(mem.len() >= BOOT_PGT.as_u64() as usize + 0x2000 + 512 * size_of::()); let pgt_slice = unsafe { std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x2000).try_into().unwrap()) as *mut u64, + mem_addr.offset(BOOT_PGT.as_u64() as isize + 0x2000) as *mut u64, 512, ) }; pgt_slice.fill(0); - pgt_slice[0] = BOOT_PGT + 0x3000 + PT_PT; - pgt_slice[1] = BOOT_PGT + 0x4000 + PT_PT; - pgt_slice[2] = BOOT_PGT + 0x5000 + PT_PT; + pgt_slice[0] = BOOT_PGT.as_u64() + 0x3000 + PT_PT; + pgt_slice[1] = BOOT_PGT.as_u64() + 0x4000 + PT_PT; + pgt_slice[2] = BOOT_PGT.as_u64() + 0x5000 + PT_PT; - assert(mem.len() >= BOOT_PGT + 0x3000 + 512 * sizeof::()); + assert!(mem.len() >= BOOT_PGT.as_u64() as usize + 0x3000 + 512 * size_of::()); let pgt_slice = unsafe { std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x3000).try_into().unwrap()) as *mut u64, + mem_addr.offset(BOOT_PGT.as_u64() as isize + 0x3000) as *mut u64, 512, ) }; @@ -106,12 +106,12 @@ pub fn init_guest_mem(mem: &mut [u8]) { // map uhyve ports into the virtual address space pgt_slice[0] = PT_MEM_CD; // map BootInfo into the virtual address space - pgt_slice[BOOT_INFO_ADDR as usize / PAGE_SIZE] = BOOT_INFO_ADDR + PT_MEM; + pgt_slice[BOOT_INFO_ADDR.as_u64() as usize / PAGE_SIZE] = BOOT_INFO_ADDR.as_u64() + PT_MEM; - assert(mem.len() >= BOOT_PGT + 0x4000 + 512 * sizeof::()); + assert!(mem.len() >= BOOT_PGT.as_u64() as usize + 0x4000 + 512 * size_of::()); let pgt_slice = unsafe { std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x4000).try_into().unwrap()) as *mut u64, + mem_addr.offset(BOOT_PGT.as_u64() as isize + 0x4000) as *mut u64, 512, ) }; @@ -119,10 +119,10 @@ pub fn init_guest_mem(mem: &mut [u8]) { *i = 0x200000u64 + (idx * PAGE_SIZE) as u64 + PT_MEM; } - assert(mem.len() >= BOOT_PGT + 0x5000 + 512 * sizeof::()); + assert!(mem.len() >= BOOT_PGT.as_u64() as usize + 0x5000 + 512 * size_of::()); let pgt_slice = unsafe { std::slice::from_raw_parts_mut( - mem_addr.offset((BOOT_PGT + 0x5000).try_into().unwrap()) as *mut u64, + mem_addr.offset(BOOT_PGT.as_u64() as isize + 0x5000) as *mut u64, 512, ) }; diff --git a/src/consts.rs b/src/consts.rs index 86250a6d..b33727f3 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,19 +1,19 @@ -use x86_64::addr::PhysAddr; +use uhyve_interface::GuestPhysAddr; pub const PAGE_SIZE: usize = 0x1000; pub const GDT_KERNEL_CODE: u16 = 1; pub const GDT_KERNEL_DATA: u16 = 2; pub const APIC_DEFAULT_BASE: u64 = 0xfee00000; -pub const BOOT_GDT: PhysAddr = PhysAddr::new(0x1000); +pub const BOOT_GDT: GuestPhysAddr = GuestPhysAddr::new(0x1000); pub const BOOT_GDT_NULL: usize = 0; pub const BOOT_GDT_CODE: usize = 1; pub const BOOT_GDT_DATA: usize = 2; pub const BOOT_GDT_MAX: usize = 3; -pub const BOOT_PML4: PhysAddr = PhysAddr::new(0x10000); -pub const BOOT_PGT: PhysAddr = BOOT_PML4; -pub const BOOT_PDPTE: PhysAddr = PhysAddr::new(0x11000); -pub const BOOT_PDE: PhysAddr = PhysAddr::new(0x12000); -pub const BOOT_INFO_ADDR: PhysAddr = PhysAddr::new(0x9000); +pub const BOOT_PML4: GuestPhysAddr = GuestPhysAddr::new(0x10000); +pub const BOOT_PGT: GuestPhysAddr = BOOT_PML4; +pub const BOOT_PDPTE: GuestPhysAddr = GuestPhysAddr::new(0x11000); +pub const BOOT_PDE: GuestPhysAddr = GuestPhysAddr::new(0x12000); +pub const BOOT_INFO_ADDR: GuestPhysAddr = GuestPhysAddr::new(0x9000); pub const EFER_SCE: u64 = 1; /* System Call Extensions */ pub const EFER_LME: u64 = 1 << 8; /* Long mode enable */ pub const EFER_LMA: u64 = 1 << 10; /* Long mode active (read-only) */ diff --git a/src/macos/aarch64/vcpu.rs b/src/macos/aarch64/vcpu.rs index 6cedb4f8..10bf0192 100644 --- a/src/macos/aarch64/vcpu.rs +++ b/src/macos/aarch64/vcpu.rs @@ -47,7 +47,8 @@ impl VirtualCPU for XhyveCpu { self.vcpu.write_register(Register::PC, entry_point)?; self.vcpu .write_system_register(SystemRegister::SP_EL1, stack_address)?; - self.vcpu.write_register(Register::X0, BOOT_INFO_ADDR)?; + self.vcpu + .write_register(Register::X0, BOOT_INFO_ADDR.as_u64())?; self.vcpu.write_register(Register::X1, cpu_id.into())?; /* @@ -99,7 +100,7 @@ impl VirtualCPU for XhyveCpu { self.vcpu .write_system_register(SystemRegister::TTBR1_EL1, 0)?; self.vcpu - .write_system_register(SystemRegister::TTBR0_EL1, BOOT_PGT)?; + .write_system_register(SystemRegister::TTBR0_EL1, BOOT_PGT.as_u64())?; /* * Prepare system control register (SCTRL) diff --git a/uhyve-interface/Cargo.toml b/uhyve-interface/Cargo.toml index 9b476d97..476848de 100644 --- a/uhyve-interface/Cargo.toml +++ b/uhyve-interface/Cargo.toml @@ -14,9 +14,13 @@ categories = ["os"] [dependencies] num_enum = { version = "0.7", default-features = false } -x86_64 = { version = "0.14", default-features = false } log = {version = "0.4", optional = true} [features] std = ["dep:log"] +[target.'cfg(target_arch = "x86_64")'.dependencies] +x86_64 = { version = "0.14", default-features = false } + +[target.'cfg(target_arch = "aarch64")'.dependencies] +aarch64 = { version = "0.0.11" , default-features = false } diff --git a/uhyve-interface/src/lib.rs b/uhyve-interface/src/lib.rs index 48135ef3..cfd33277 100644 --- a/uhyve-interface/src/lib.rs +++ b/uhyve-interface/src/lib.rs @@ -15,10 +15,15 @@ use num_enum::TryFromPrimitive; pub mod elf; pub mod parameters; +#[cfg(target_arch = "aarch64")] +pub use ::aarch64::paging::PhysAddr as GuestPhysAddr; +#[cfg(target_arch = "aarch64")] +pub use ::aarch64::paging::VirtAddr as GuestVirtAddr; #[cfg(target_arch = "x86_64")] pub use ::x86_64::addr::PhysAddr as GuestPhysAddr; #[cfg(target_arch = "x86_64")] pub use ::x86_64::addr::VirtAddr as GuestVirtAddr; + #[cfg(not(target_pointer_width = "64"))] compile_error!("Using uhyve-interface on a non-64-bit system is not (yet?) supported"); use parameters::*; From e839c5da445f8f7eceefe8e8f3494e4f00eba0d2 Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Tue, 12 Mar 2024 15:28:06 +0100 Subject: [PATCH 4/7] Adapted macos to new UhveVm architecture --- src/macos/aarch64/mod.rs | 1 - src/macos/aarch64/uhyve.rs | 175 ------------------------------------- src/macos/aarch64/vcpu.rs | 53 +++++------ src/macos/mod.rs | 4 +- src/vm.rs | 2 +- 5 files changed, 26 insertions(+), 209 deletions(-) delete mode 100644 src/macos/aarch64/uhyve.rs diff --git a/src/macos/aarch64/mod.rs b/src/macos/aarch64/mod.rs index 58cca2f3..f1096356 100644 --- a/src/macos/aarch64/mod.rs +++ b/src/macos/aarch64/mod.rs @@ -1,4 +1,3 @@ -pub mod uhyve; pub mod vcpu; /// The size of a page. diff --git a/src/macos/aarch64/uhyve.rs b/src/macos/aarch64/uhyve.rs deleted file mode 100644 index f35fd4f8..00000000 --- a/src/macos/aarch64/uhyve.rs +++ /dev/null @@ -1,175 +0,0 @@ -use std::{ - ffi::OsString, - path::{Path, PathBuf}, - ptr, -}; - -use hermit_entry::boot_info::RawBootInfo; -use libc::{self, c_void}; -use log::debug; -use xhypervisor::{create_vm, map_mem, unmap_mem, MemPerm}; - -use crate::{ - aarch64::{PT_MEM, PT_MEM_CD, PT_PT, PT_SELF}, - consts::{BOOT_INFO_ADDR, BOOT_PGT, PAGE_SIZE}, - macos::aarch64::{vcpu::*, HYPERVISOR_PAGE_SIZE}, - params::Params, - vm::{HypervisorResult, Vm}, -}; - -pub struct Uhyve { - offset: u64, - entry_point: u64, - stack_address: u64, - mem_size: usize, - guest_mem: *mut c_void, - num_cpus: u32, - path: PathBuf, - args: Vec, - boot_info: *const RawBootInfo, - verbose: bool, -} - -impl std::fmt::Debug for Uhyve { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Uhyve") - .field("entry_point", &self.entry_point) - .field("stack_address", &self.stack_address) - .field("mem_size", &self.mem_size) - .field("guest_mem", &self.guest_mem) - .field("num_cpus", &self.num_cpus) - .field("path", &self.path) - .field("boot_info", &self.boot_info) - .field("verbose", &self.verbose) - .finish() - } -} - -impl Uhyve { - pub fn new(kernel_path: PathBuf, params: Params) -> HypervisorResult { - let memory_size = params.memory_size.get(); - - assert!(HYPERVISOR_PAGE_SIZE < memory_size); - - let mem = unsafe { - libc::mmap( - std::ptr::null_mut(), - memory_size, - libc::PROT_READ | libc::PROT_WRITE, - libc::MAP_PRIVATE | libc::MAP_ANON | libc::MAP_NORESERVE, - -1, - 0, - ) - }; - - assert_ne!(libc::MAP_FAILED, mem, "mmap failed"); - - debug!("Allocate memory for the guest at 0x{:x}", mem as usize); - - debug!("Create VM..."); - create_vm()?; - - debug!("Map guest memory..."); - unsafe { - map_mem( - std::slice::from_raw_parts(mem as *mut u8, HYPERVISOR_PAGE_SIZE), - 0, - MemPerm::Read, - )?; - - map_mem( - std::slice::from_raw_parts_mut( - (mem as *mut u8).offset(HYPERVISOR_PAGE_SIZE.try_into().unwrap()), - memory_size - HYPERVISOR_PAGE_SIZE, - ), - HYPERVISOR_PAGE_SIZE.try_into().unwrap(), - MemPerm::ExecAndWrite, - )?; - } - - let hyve = Uhyve { - offset: 0, - entry_point: 0, - stack_address: 0, - mem_size: memory_size, - guest_mem: mem, - num_cpus: params.cpu_count.get(), - path: kernel_path, - args: params.kernel_args, - boot_info: ptr::null(), - verbose: params.verbose, - }; - - hyve.init_guest_mem(); - - Ok(hyve) - } -} - -impl Vm for Uhyve { - fn verbose(&self) -> bool { - self.verbose - } - - fn set_offset(&mut self, offset: u64) { - self.offset = offset; - } - - fn get_offset(&self) -> u64 { - self.offset - } - - fn set_entry_point(&mut self, entry: u64) { - self.entry_point = entry; - } - - fn get_entry_point(&self) -> u64 { - self.entry_point - } - - fn set_stack_address(&mut self, stack_address: u64) { - self.stack_address = stack_address; - } - - fn stack_address(&self) -> u64 { - self.stack_address - } - - fn num_cpus(&self) -> u32 { - self.num_cpus - } - - fn guest_mem(&self) -> (*mut u8, usize) { - (self.guest_mem as *mut u8, self.mem_size) - } - - fn kernel_path(&self) -> &Path { - self.path.as_path() - } - - fn create_cpu(&self, id: u32) -> HypervisorResult { - Ok(XhyveCpu::new( - id, - self.path.clone(), - self.args.clone(), - self.guest_mem as usize, - )) - } - - fn set_boot_info(&mut self, header: *const RawBootInfo) { - self.boot_info = header; - } -} - -impl Drop for Uhyve { - fn drop(&mut self) { - unmap_mem(0, self.mem_size).unwrap(); - - unsafe { - libc::munmap(self.guest_mem, self.mem_size); - } - } -} - -unsafe impl Send for Uhyve {} -unsafe impl Sync for Uhyve {} diff --git a/src/macos/aarch64/vcpu.rs b/src/macos/aarch64/vcpu.rs index 10bf0192..0d7910bc 100644 --- a/src/macos/aarch64/vcpu.rs +++ b/src/macos/aarch64/vcpu.rs @@ -1,13 +1,10 @@ #![allow(non_snake_case)] #![allow(clippy::identity_op)] -use std::{ - ffi::OsString, - path::{Path, PathBuf}, -}; +use std::sync::Arc; use log::debug; -use uhyve_interface::Hypercall; +use uhyve_interface::{GuestPhysAddr, Hypercall}; use xhypervisor::{self, Register, SystemRegister, VirtualCpuExitReason}; use crate::{ @@ -16,28 +13,19 @@ use crate::{ PSR, TCR_FLAGS, TCR_TG1_4K, VA_BITS, }, consts::*, - vm::{HypervisorResult, VcpuStopReason, VirtualCPU}, + hypercall, + vcpu::{VcpuStopReason, VirtualCPU}, + vm::UhyveVm, + HypervisorResult, }; pub struct XhyveCpu { id: u32, - kernel_path: PathBuf, - args: Vec, vcpu: xhypervisor::VirtualCpu, + parent_vm: Arc>, } impl XhyveCpu { - pub fn new(id: u32, kernel_path: PathBuf, args: Vec) -> XhyveCpu { - Self { - id, - kernel_path, - args, - vcpu: xhypervisor::VirtualCpu::new().unwrap(), - } - } -} - -impl VirtualCPU for XhyveCpu { fn init(&mut self, entry_point: u64, stack_address: u64, cpu_id: u32) -> HypervisorResult<()> { debug!("Initialize VirtualCPU"); @@ -145,13 +133,18 @@ impl VirtualCPU for XhyveCpu { Ok(()) } +} - fn kernel_path(&self) -> &Path { - self.kernel_path.as_path() - } +impl VirtualCPU for XhyveCpu { + fn new(id: u32, parent_vm: Arc>) -> HypervisorResult { + let mut vcpu = XhyveCpu { + id, + parent_vm: parent_vm.clone(), + vcpu: xhypervisor::VirtualCpu::new().unwrap(), + }; + vcpu.init(parent_vm.get_entry_point(), parent_vm.stack_address(), id)?; - fn args(&self) -> &[OsString] { - self.args.as_slice() + Ok(vcpu) } fn r#continue(&mut self) -> HypervisorResult { @@ -168,18 +161,18 @@ impl VirtualCPU for XhyveCpu { let addr: u16 = exception.physical_address.try_into().unwrap(); let pc = self.vcpu.read_register(Register::PC)?; - let data_addr = self.vcpu.read_register(Register::X8)?; - if let Some(hypercall) = - unsafe { self.address_to_hypercall(addr, data_addr as usize) } - { + let data_addr = GuestPhysAddr::new(self.vcpu.read_register(Register::X8)?); + if let Some(hypercall) = unsafe { + hypercall::address_to_hypercall(&self.parent_vm.mem, addr, data_addr) + } { match hypercall { Hypercall::SerialWriteByte(_char) => { let x8 = (self.vcpu.read_register(Register::X8)? & 0xFF) as u8; - self.uart(&[x8]).unwrap(); + hypercall::uart(&[x8]).unwrap(); } Hypercall::Exit(sysexit) => { - return Ok(VcpuStopReason::Exit(self.exit(sysexit))); + return Ok(VcpuStopReason::Exit(sysexit.arg)); } _ => { panic! {"Hypercall {hypercall:?} not implemented on macos-aarch64"} diff --git a/src/macos/mod.rs b/src/macos/mod.rs index 7397eab9..1c58ce18 100644 --- a/src/macos/mod.rs +++ b/src/macos/mod.rs @@ -12,9 +12,9 @@ use std::{ use core_affinity::CoreId; #[cfg(target_arch = "aarch64")] -pub use crate::macos::aarch64::{uhyve, vcpu}; +pub use crate::macos::aarch64::vcpu::XhyveCpu; #[cfg(target_arch = "x86_64")] -use crate::macos::x86_64::vcpu::XhyveCpu; +pub use crate::macos::x86_64::vcpu::XhyveCpu; use crate::{vcpu::VirtualCPU, vm::UhyveVm}; pub type HypervisorError = xhypervisor::Error; diff --git a/src/vm.rs b/src/vm.rs index a01010bf..8f0ba51a 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -68,7 +68,7 @@ fn detect_cpu_freq() -> u32 { #[cfg(target_os = "linux")] pub type VcpuDefault = crate::linux::x86_64::kvm_cpu::KvmCpu; #[cfg(target_os = "macos")] -pub type VcpuDefault = crate::macos::x86_64::vcpu::XhyveCpu; +pub type VcpuDefault = crate::macos::XhyveCpu; pub struct UhyveVm { /// The starting position of the image in physical memory From 7d45f98bf3f61b14e0869ef751284ac0b39bcc80 Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Tue, 12 Mar 2024 15:28:06 +0100 Subject: [PATCH 5/7] Added virt_to_phys fn for aarch64 --- src/arch/aarch64/mod.rs | 91 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 88 insertions(+), 3 deletions(-) diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index cc203067..d92e30b1 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -1,7 +1,13 @@ -use crate::consts::{BOOT_INFO_ADDR, BOOT_PGT, PAGE_SIZE}; -use bitflags::bitflags; use std::mem::size_of; -use uhyve_interface::GuestPhysAddr; + +use bitflags::bitflags; +use uhyve_interface::{GuestPhysAddr, GuestVirtAddr}; + +use crate::{ + consts::{BOOT_INFO_ADDR, BOOT_PGT}, + mem::MmapMemory, + paging::PagetableError, +}; pub const RAM_START: GuestPhysAddr = GuestPhysAddr::new(0x00); @@ -22,6 +28,16 @@ pub const MT_DEVICE_GRE: u64 = 2; pub const MT_NORMAL_NC: u64 = 3; pub const MT_NORMAL: u64 = 4; +/// Number of Offset bits of a virtual address for a 4 KiB page, which are shifted away to get its Page Frame Number (PFN). +const PAGE_BITS: usize = 12; +const PAGE_SIZE: usize = 1 << PAGE_BITS; + +/// Number of bits of the index in each table (L0Table, L1Table, L2Table, L3Table). +const PAGE_MAP_BITS: usize = 9; + +/// A mask where PAGE_MAP_BITS are set to calculate a table index. +const PAGE_MAP_MASK: u64 = 0x1FF; + #[inline(always)] pub const fn mair(attr: u64, mt: u64) -> u64 { attr << (mt * 8) @@ -62,6 +78,75 @@ bitflags! { } } +/// An entry in a L0 page table (coarses). Adapted from hermit-os/kernel. +#[derive(Clone, Copy, Debug)] +struct PageTableEntry { + /// Physical memory address this entry refers, combined with flags from PageTableEntryFlags. + physical_address_and_flags: GuestPhysAddr, +} + +impl PageTableEntry { + /// Return the stored physical address. + pub fn address(&self) -> GuestPhysAddr { + // For other granules than 4KiB or hugepages we should check the DESCRIPTOR_TYPE bit and modify the address translation accordingly. + GuestPhysAddr( + self.physical_address_and_flags.as_u64() & !(PAGE_SIZE as u64 - 1) & !(u64::MAX << 48), + ) + } +} +impl From for PageTableEntry { + fn from(i: u64) -> Self { + Self { + physical_address_and_flags: GuestPhysAddr::new(i), + } + } +} + +/// Returns whether the given virtual address is a valid one in the AArch64 memory model. +/// +/// Current AArch64 supports only 48-bit for virtual memory addresses. +/// The upper bits must always be 0 or 1 and indicate whether TBBR0 or TBBR1 contains the +/// base address. So always enforce 0 here. +fn is_valid_address(virtual_address: GuestVirtAddr) -> bool { + virtual_address < GuestVirtAddr(0x1_0000_0000_0000) +} + +/// Converts a virtual address in the guest to a physical address in the guest +pub fn virt_to_phys( + addr: GuestVirtAddr, + mem: &MmapMemory, +) -> Result { + if !is_valid_address(addr) { + return Err(PagetableError::InvalidAddress); + } + + // Assumptions: + // - We use 4KiB granule + // - We use maximum VA length + // => We have 4 level paging + + // Safety: + // - We are only working in the vm's memory + // - the memory location of the pagetable is not altered by hermit. + // - Our indices can't be larger than 512, so we stay in the borders of the page. + // - We are page_aligned, and thus also PageTableEntry aligned. + let mut pagetable: &[PageTableEntry] = + unsafe { std::mem::transmute(mem.slice_at(BOOT_PGT, PAGE_SIZE).unwrap()) }; + // TODO: Depending on the virtual address length and granule (defined in TCR register by TG and TxSZ), we could reduce the number of pagetable walks. Hermit doesn't do this at the moment. + for level in 0..3 { + let table_index = + (addr.as_u64() >> PAGE_BITS >> ((3 - level) * PAGE_MAP_BITS) & PAGE_MAP_MASK) as usize; + let pte = PageTableEntry::from(pagetable[table_index]); + // TODO: We could stop here if we have a "Block Entry" (ARM equivalent to huge page). Currently not supported. + + pagetable = unsafe { std::mem::transmute(mem.slice_at(pte.address(), PAGE_SIZE).unwrap()) }; + } + let table_index = (addr.as_u64() >> PAGE_BITS & PAGE_MAP_MASK) as usize; + let pte = PageTableEntry::from(pagetable[table_index]); + + Ok(pte.address()) +} + pub fn init_guest_mem(mem: &mut [u8]) { let mem_addr = std::ptr::addr_of_mut!(mem[0]); From c7da62faeb997a5f6cbe35fc5768cc58a8b1311c Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Tue, 12 Mar 2024 15:28:06 +0100 Subject: [PATCH 6/7] changed the pagetable location to be a parameter of fn virt_to_phys --- src/arch/aarch64/mod.rs | 3 ++- src/arch/x86_64/mod.rs | 11 ++++++----- src/hypercall.rs | 23 +++++++++++++---------- src/linux/gdb/breakpoints.rs | 12 ++++++++---- src/linux/gdb/mod.rs | 6 ++++-- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index d92e30b1..8c91caa6 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -115,6 +115,7 @@ fn is_valid_address(virtual_address: GuestVirtAddr) -> bool { pub fn virt_to_phys( addr: GuestVirtAddr, mem: &MmapMemory, + pagetable_l0: GuestPhysAddr, ) -> Result { if !is_valid_address(addr) { return Err(PagetableError::InvalidAddress); @@ -131,7 +132,7 @@ pub fn virt_to_phys( // - Our indices can't be larger than 512, so we stay in the borders of the page. // - We are page_aligned, and thus also PageTableEntry aligned. let mut pagetable: &[PageTableEntry] = - unsafe { std::mem::transmute(mem.slice_at(BOOT_PGT, PAGE_SIZE).unwrap()) }; + unsafe { std::mem::transmute(mem.slice_at(pagetable_l0, PAGE_SIZE).unwrap()) }; // TODO: Depending on the virtual address length and granule (defined in TCR register by TG and TxSZ), we could reduce the number of pagetable walks. Hermit doesn't do this at the moment. for level in 0..3 { let table_index = diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 20f70853..2593231c 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -196,6 +196,7 @@ pub fn initialize_pagetables(mem: &mut [u8]) { pub fn virt_to_phys( addr: GuestVirtAddr, mem: &MmapMemory, + pagetable_l0: GuestPhysAddr, ) -> Result { /// Number of Offset bits of a virtual address for a 4 KiB page, which are shifted away to get its Page Frame Number (PFN). pub const PAGE_BITS: u64 = 12; @@ -204,7 +205,7 @@ pub fn virt_to_phys( pub const PAGE_MAP_BITS: usize = 9; let mut page_table = - unsafe { (mem.host_address(BOOT_PML4).unwrap() as *mut PageTable).as_mut() }.unwrap(); + unsafe { (mem.host_address(pagetable_l0).unwrap() as *mut PageTable).as_mut() }.unwrap(); let mut page_bits = 39; let mut entry = PageTableEntry::new(); @@ -379,12 +380,12 @@ mod tests { // Get the address of the first entry in PML4 (the address of the PML4 itself) let virt_addr = GuestVirtAddr::new(0xFFFFFFFFFFFFF000); - let p_addr = virt_to_phys(virt_addr, &mem).unwrap(); + let p_addr = virt_to_phys(virt_addr, &mem, BOOT_PML4).unwrap(); assert_eq!(p_addr, BOOT_PML4); // The last entry on the PML4 is the address of the PML4 with flags let virt_addr = GuestVirtAddr::new(0xFFFFFFFFFFFFF000 | (4096 - 8)); - let p_addr = virt_to_phys(virt_addr, &mem).unwrap(); + let p_addr = virt_to_phys(virt_addr, &mem, BOOT_PML4).unwrap(); assert_eq!( mem.read::(p_addr).unwrap(), BOOT_PML4.as_u64() | (PageTableFlags::PRESENT | PageTableFlags::WRITABLE).bits() @@ -392,12 +393,12 @@ mod tests { // the first entry on the 3rd level entry in the pagetables is the address of the boot pdpte let virt_addr = GuestVirtAddr::new(0xFFFFFFFFFFE00000); - let p_addr = virt_to_phys(virt_addr, &mem).unwrap(); + let p_addr = virt_to_phys(virt_addr, &mem, BOOT_PML4).unwrap(); assert_eq!(p_addr, BOOT_PDPTE); // the first entry on the 2rd level entry in the pagetables is the address of the boot pde let virt_addr = GuestVirtAddr::new(0xFFFFFFFFC0000000); - let p_addr = virt_to_phys(virt_addr, &mem).unwrap(); + let p_addr = virt_to_phys(virt_addr, &mem, BOOT_PML4).unwrap(); assert_eq!(p_addr, BOOT_PDE); // That address points to a huge page assert!( diff --git a/src/hypercall.rs b/src/hypercall.rs index 47921ec6..0205419c 100644 --- a/src/hypercall.rs +++ b/src/hypercall.rs @@ -7,6 +7,7 @@ use std::{ use uhyve_interface::{parameters::*, GuestPhysAddr, Hypercall, HypercallAddress, MAX_ARGC_ENVC}; use crate::{ + consts::BOOT_PML4, mem::{MemoryError, MmapMemory}, virt_to_phys, }; @@ -101,7 +102,7 @@ pub fn read(mem: &MmapMemory, sysread: &mut ReadPrams) { unsafe { let bytes_read = libc::read( sysread.fd, - mem.host_address(virt_to_phys(sysread.buf, mem).unwrap()) + mem.host_address(virt_to_phys(sysread.buf, mem, BOOT_PML4).unwrap()) .unwrap() as *mut libc::c_void, sysread.len, ); @@ -120,15 +121,17 @@ pub fn write(mem: &MmapMemory, syswrite: &WriteParams) -> io::Result<()> { unsafe { let step = libc::write( syswrite.fd, - mem.host_address(virt_to_phys(syswrite.buf + bytes_written as u64, mem).unwrap()) - .map_err(|e| match e { - MemoryError::BoundsViolation => { - unreachable!("Bounds violation after host_address function") - } - MemoryError::WrongMemoryError => { - Error::new(ErrorKind::AddrNotAvailable, e.to_string()) - } - })? as *const libc::c_void, + mem.host_address( + virt_to_phys(syswrite.buf + bytes_written as u64, mem, BOOT_PML4).unwrap(), + ) + .map_err(|e| match e { + MemoryError::BoundsViolation => { + unreachable!("Bounds violation after host_address function") + } + MemoryError::WrongMemoryError => { + Error::new(ErrorKind::AddrNotAvailable, e.to_string()) + } + })? as *const libc::c_void, syswrite.len - bytes_written, ); if step >= 0 { diff --git a/src/linux/gdb/breakpoints.rs b/src/linux/gdb/breakpoints.rs index 8de01a70..454f9cdf 100644 --- a/src/linux/gdb/breakpoints.rs +++ b/src/linux/gdb/breakpoints.rs @@ -4,8 +4,10 @@ use gdbstub::target::{self, ext::breakpoints::WatchKind, TargetResult}; use uhyve_interface::GuestVirtAddr; use super::GdbUhyve; -use crate::arch::x86_64::{registers, virt_to_phys}; - +use crate::{ + arch::x86_64::{registers, virt_to_phys}, + consts::BOOT_PML4, +}; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct SwBreakpoint { addr: u64, @@ -53,7 +55,8 @@ impl target::ext::breakpoints::SwBreakpoint for GdbUhyve { // Safety: mem is not altered during the lifetime of `instructions` let instructions = unsafe { self.vm.mem.slice_at_mut( - virt_to_phys(GuestVirtAddr::new(addr), &self.vm.mem).map_err(|_err| ())?, + virt_to_phys(GuestVirtAddr::new(addr), &self.vm.mem, BOOT_PML4) + .map_err(|_err| ())?, kind, ) } @@ -73,7 +76,8 @@ impl target::ext::breakpoints::SwBreakpoint for GdbUhyve { // Safety: mem is not altered during the lifetime of `instructions` let instructions = unsafe { self.vm.mem.slice_at_mut( - virt_to_phys(GuestVirtAddr::new(addr), &self.vm.mem).map_err(|_err| ())?, + virt_to_phys(GuestVirtAddr::new(addr), &self.vm.mem, BOOT_PML4) + .map_err(|_err| ())?, kind, ) } diff --git a/src/linux/gdb/mod.rs b/src/linux/gdb/mod.rs index 29f08e3a..5dd525f0 100644 --- a/src/linux/gdb/mod.rs +++ b/src/linux/gdb/mod.rs @@ -30,6 +30,7 @@ use self::breakpoints::SwBreakpoints; use super::HypervisorError; use crate::{ arch::x86_64::{registers::debug::HwBreakpoints, virt_to_phys}, + consts::BOOT_PML4, linux::{x86_64::kvm_cpu::KvmCpu, KickSignal}, vcpu::{VcpuStopReason, VirtualCPU}, vm::UhyveVm, @@ -130,7 +131,7 @@ impl SingleThreadBase for GdbUhyve { // Safety: mem is copied to data before mem can be modified. let src = unsafe { self.vm.mem.slice_at( - virt_to_phys(guest_addr, &self.vm.mem).map_err(|_err| ())?, + virt_to_phys(guest_addr, &self.vm.mem, BOOT_PML4).map_err(|_err| ())?, data.len(), ) } @@ -143,7 +144,8 @@ impl SingleThreadBase for GdbUhyve { // Safety: self.vm.mem is not altered during the lifetime of mem. let mem = unsafe { self.vm.mem.slice_at_mut( - virt_to_phys(GuestVirtAddr::new(start_addr), &self.vm.mem).map_err(|_err| ())?, + virt_to_phys(GuestVirtAddr::new(start_addr), &self.vm.mem, BOOT_PML4) + .map_err(|_err| ())?, data.len(), ) } From c086b3ee5814caad38e04b28557e925ab05fcc8c Mon Sep 17 00:00:00 2001 From: Jonathan Klimt Date: Tue, 12 Mar 2024 15:28:06 +0100 Subject: [PATCH 7/7] Untested add of the file hypercall functions --- src/macos/aarch64/vcpu.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/macos/aarch64/vcpu.rs b/src/macos/aarch64/vcpu.rs index 0d7910bc..35d86869 100644 --- a/src/macos/aarch64/vcpu.rs +++ b/src/macos/aarch64/vcpu.rs @@ -13,7 +13,7 @@ use crate::{ PSR, TCR_FLAGS, TCR_TG1_4K, VA_BITS, }, consts::*, - hypercall, + hypercall::{self, copy_argv, copy_env}, vcpu::{VcpuStopReason, VirtualCPU}, vm::UhyveVm, HypervisorResult, @@ -174,6 +174,31 @@ impl VirtualCPU for XhyveCpu { Hypercall::Exit(sysexit) => { return Ok(VcpuStopReason::Exit(sysexit.arg)); } + Hypercall::Cmdsize(syssize) => syssize + .update(self.parent_vm.kernel_path(), self.parent_vm.args()), + Hypercall::Cmdval(syscmdval) => { + copy_argv( + self.parent_vm.kernel_path().as_os_str(), + self.parent_vm.args(), + syscmdval, + &self.parent_vm.mem, + ); + copy_env(syscmdval, &self.parent_vm.mem); + } + Hypercall::FileClose(sysclose) => hypercall::close(sysclose), + Hypercall::FileLseek(syslseek) => hypercall::lseek(syslseek), + Hypercall::FileOpen(sysopen) => { + hypercall::open(&self.parent_vm.mem, sysopen) + } + Hypercall::FileRead(sysread) => { + hypercall::read(&self.parent_vm.mem, sysread) + } + Hypercall::FileWrite(syswrite) => { + hypercall::write(&self.parent_vm.mem, syswrite).unwrap() + } + Hypercall::FileUnlink(sysunlink) => { + hypercall::unlink(&self.parent_vm.mem, sysunlink) + } _ => { panic! {"Hypercall {hypercall:?} not implemented on macos-aarch64"} }