From 7187617304e75024bd7f5aaa3b3469088d120984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Sat, 21 Sep 2024 11:17:20 +0200 Subject: [PATCH 1/4] refactor(uhyve): unify `uhyve_send` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/syscalls/interfaces/uhyve.rs | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/syscalls/interfaces/uhyve.rs b/src/syscalls/interfaces/uhyve.rs index fa7267418a..a15f55e75f 100644 --- a/src/syscalls/interfaces/uhyve.rs +++ b/src/syscalls/interfaces/uhyve.rs @@ -3,9 +3,6 @@ use alloc::boxed::Box; use alloc::vec::Vec; use core::{mem, ptr}; -#[cfg(target_arch = "x86_64")] -use x86::io::*; - use crate::arch; use crate::arch::mm::{paging, PhysAddr, VirtAddr}; use crate::syscalls::interfaces::SyscallInterface; @@ -16,40 +13,27 @@ const UHYVE_PORT_CMDVAL: u16 = 0x780; /// forward a request to the hypervisor uhyve #[inline] -#[cfg(target_arch = "x86_64")] fn uhyve_send(port: u16, data: &mut T) { let ptr = VirtAddr(ptr::from_mut(data).addr() as u64); let physical_address = paging::virtual_to_physical(ptr).unwrap(); + #[cfg(target_arch = "x86_64")] unsafe { - outl(port, physical_address.as_u64() as u32); + x86::io::outl(port, physical_address.as_u64() as u32); } -} - -/// forward a request to the hypervisor uhyve -#[inline] -#[cfg(target_arch = "aarch64")] -fn uhyve_send(port: u16, data: &mut T) { - use core::arch::asm; - - let ptr = VirtAddr(ptr::from_mut(data).addr() as u64); - let physical_address = paging::virtual_to_physical(ptr).unwrap(); + #[cfg(target_arch = "aarch64")] unsafe { - asm!( + core::arch::asm!( "str x8, [{port}]", port = in(reg) u64::from(port), in("x8") physical_address.as_u64(), options(nostack), ); } -} -/// forward a request to the hypervisor uhyve -#[inline] -#[cfg(target_arch = "riscv64")] -fn uhyve_send(_port: u16, _data: &mut T) { - todo!() + #[cfg(target_arch = "riscv64")] + todo!("uhyve_send(port = {port}, physical_address = {physical_address})"); } const MAX_ARGC_ENVC: usize = 128; From 5eecd6e68a9349445d190989aecc531ddf78b310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 20 Sep 2024 13:13:36 +0200 Subject: [PATCH 2/4] feat(env): parse FDT bootargs on all platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/arch/aarch64/kernel/mod.rs | 10 +--------- src/arch/riscv64/kernel/mod.rs | 5 +---- src/env.rs | 24 +++++++++++++++++++----- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/arch/aarch64/kernel/mod.rs b/src/arch/aarch64/kernel/mod.rs index ae58bd364a..48557f6226 100644 --- a/src/arch/aarch64/kernel/mod.rs +++ b/src/arch/aarch64/kernel/mod.rs @@ -91,15 +91,7 @@ pub fn get_processor_count() -> u32 { } pub fn args() -> Option<&'static str> { - let dtb = unsafe { - hermit_dtb::Dtb::from_raw(ptr::with_exposed_provenance( - boot_info().hardware_info.device_tree.unwrap().get() as usize, - )) - .expect(".dtb file has invalid header") - }; - - dtb.get_property("/chosen", "bootargs") - .map(|property| str::from_utf8(property).unwrap()) + None } /// Earliest initialization function called by the Boot Processor. diff --git a/src/arch/riscv64/kernel/mod.rs b/src/arch/riscv64/kernel/mod.rs index 5adcb3376e..93593d8908 100644 --- a/src/arch/riscv64/kernel/mod.rs +++ b/src/arch/riscv64/kernel/mod.rs @@ -84,10 +84,7 @@ pub fn get_base_address() -> VirtAddr { } pub fn args() -> Option<&'static str> { - unsafe { - let fdt = Fdt::from_ptr(get_dtb_ptr()).expect("FDT is invalid"); - fdt.chosen().bootargs() - } + None } pub fn get_dtb_ptr() -> *const u8 { diff --git a/src/env.rs b/src/env.rs index 0987352b71..a073f27ecc 100644 --- a/src/env.rs +++ b/src/env.rs @@ -2,9 +2,10 @@ use alloc::string::{String, ToString}; use alloc::vec::Vec; -use core::str; +use core::{ptr, str}; use ahash::RandomState; +use fdt::Fdt; use hashbrown::hash_map::Iter; use hashbrown::HashMap; use hermit_entry::boot_info::PlatformInfo; @@ -36,6 +37,17 @@ pub fn is_uhyve() -> bool { matches!(boot_info().platform_info, PlatformInfo::Uhyve { .. }) } +pub fn fdt() -> Option> { + kernel::boot_info().hardware_info.device_tree.map(|fdt| { + let ptr = ptr::with_exposed_provenance(fdt.get().try_into().unwrap()); + unsafe { Fdt::from_ptr(ptr).unwrap() } + }) +} + +pub fn fdt_args() -> Option<&'static str> { + fdt().and_then(|fdt| fdt.chosen().bootargs()) +} + impl Default for Cli { fn default() -> Self { let mut image_path = None; @@ -44,11 +56,10 @@ impl Default for Cli { let mut env_vars = HashMap::::with_hasher( RandomState::with_seeds(0, 0, 0, 0), ); - let mut args = Vec::new(); - let mut mmio = Vec::new(); - let words = shell_words::split(kernel::args().unwrap_or_default()).unwrap(); - debug!("cli_words = {words:?}"); + let args = kernel::args().or_else(fdt_args).unwrap_or_default(); + info!("bootargs = {args}"); + let words = shell_words::split(args).unwrap(); let mut words = words.into_iter(); let expect_arg = |arg: Option, name: &str| { @@ -56,6 +67,9 @@ impl Default for Cli { panic!("The argument '{name}' requires a value but none was supplied") }) }; + + let mut args = Vec::new(); + let mut mmio = Vec::new(); while let Some(word) = words.next() { if word.as_str().starts_with("virtio_mmio.device=") { let v: Vec<&str> = word.as_str().split('=').collect(); From c0e9cc135b9ab0eac27e81fd8816dbdb1b7bb187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 20 Sep 2024 14:00:40 +0200 Subject: [PATCH 3/4] feat(env): parse `env=KEY=VALUE` for env vars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/env.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/env.rs b/src/env.rs index a073f27ecc..8251a94408 100644 --- a/src/env.rs +++ b/src/env.rs @@ -100,12 +100,22 @@ impl Default for Cli { env_vars.insert(String::from("UHYVE_MOUNT"), gateway); } "--" => args.extend(&mut words), + word if word.contains('=') => { + let (arg, value) = word.split_once('=').unwrap(); + + match arg { + "env" => { + let Some((key, value)) = value.split_once('=') else { + error!("could not parse bootarg: {word}"); + continue; + }; + env_vars.insert(key.to_string(), value.to_string()); + } + _ => error!("could not parse bootarg: {word}"), + } + } _ if image_path.is_none() => image_path = Some(word), - word => warn!( - "Found argument '{word}' which wasn't expected, or isn't valid in this context - - If you tried to supply `{word}` as a value rather than a flag, use `-- {word}`" - ), + word => error!("could not parse bootarg: {word}"), }; } From a5f952bedc4a4137b1383cd137d578acd9b77a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Fri, 20 Sep 2024 14:01:17 +0200 Subject: [PATCH 4/4] feat(uhyve): don't override `get_application_parameters` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Martin Kröning --- src/syscalls/interfaces/uhyve.rs | 101 +------------------------------ 1 file changed, 2 insertions(+), 99 deletions(-) diff --git a/src/syscalls/interfaces/uhyve.rs b/src/syscalls/interfaces/uhyve.rs index a15f55e75f..595b8aff73 100644 --- a/src/syscalls/interfaces/uhyve.rs +++ b/src/syscalls/interfaces/uhyve.rs @@ -1,15 +1,10 @@ -use alloc::alloc::{alloc, Layout}; -use alloc::boxed::Box; -use alloc::vec::Vec; -use core::{mem, ptr}; +use core::ptr; use crate::arch; -use crate::arch::mm::{paging, PhysAddr, VirtAddr}; +use crate::arch::mm::{paging, VirtAddr}; use crate::syscalls::interfaces::SyscallInterface; const UHYVE_PORT_EXIT: u16 = 0x540; -const UHYVE_PORT_CMDSIZE: u16 = 0x740; -const UHYVE_PORT_CMDVAL: u16 = 0x780; /// forward a request to the hypervisor uhyve #[inline] @@ -36,42 +31,6 @@ fn uhyve_send(port: u16, data: &mut T) { todo!("uhyve_send(port = {port}, physical_address = {physical_address})"); } -const MAX_ARGC_ENVC: usize = 128; - -#[repr(C, packed)] -struct SysCmdsize { - argc: i32, - argsz: [i32; MAX_ARGC_ENVC], - envc: i32, - envsz: [i32; MAX_ARGC_ENVC], -} - -impl SysCmdsize { - fn new() -> SysCmdsize { - SysCmdsize { - argc: 0, - argsz: [0; MAX_ARGC_ENVC], - envc: 0, - envsz: [0; MAX_ARGC_ENVC], - } - } -} - -#[repr(C, packed)] -struct SysCmdval { - argv: PhysAddr, - envp: PhysAddr, -} - -impl SysCmdval { - fn new(argv: VirtAddr, envp: VirtAddr) -> SysCmdval { - SysCmdval { - argv: paging::virtual_to_physical(argv).unwrap(), - envp: paging::virtual_to_physical(envp).unwrap(), - } - } -} - #[repr(C, packed)] struct SysExit { arg: i32, @@ -86,62 +45,6 @@ impl SysExit { pub struct Uhyve; impl SyscallInterface for Uhyve { - /// ToDo: This function needs a description - also applies to trait in src/syscalls/interfaces/mod.rs - /// - /// ToDo: Add Safety section under which circumctances this is safe/unsafe to use - /// ToDo: Add an Errors section - What happens when e.g. malloc fails, how is that handled (currently it isn't) - #[cfg(target_os = "none")] - fn get_application_parameters(&self) -> (i32, *const *const u8, *const *const u8) { - // determine the number of arguments and environment variables - let mut syscmdsize = SysCmdsize::new(); - uhyve_send(UHYVE_PORT_CMDSIZE, &mut syscmdsize); - - // create array to receive all arguments - let mut argv = Box::new(Vec::with_capacity(syscmdsize.argc as usize)); - let mut argv_phy = Vec::with_capacity(syscmdsize.argc as usize); - for i in 0..syscmdsize.argc as usize { - let layout = - Layout::from_size_align(syscmdsize.argsz[i] as usize * mem::size_of::(), 1) - .unwrap(); - - argv.push(unsafe { alloc(layout).cast_const() }); - - argv_phy.push(ptr::with_exposed_provenance::( - paging::virtual_to_physical(VirtAddr(argv[i] as u64)) - .unwrap() - .as_usize(), - )); - } - - // create array to receive the environment - let mut env = Box::new(Vec::with_capacity(syscmdsize.envc as usize + 1)); - let mut env_phy = Vec::with_capacity(syscmdsize.envc as usize + 1); - for i in 0..syscmdsize.envc as usize { - let layout = - Layout::from_size_align(syscmdsize.envsz[i] as usize * mem::size_of::(), 1) - .unwrap(); - env.push(unsafe { alloc(layout).cast_const() }); - - env_phy.push(ptr::with_exposed_provenance::( - paging::virtual_to_physical(VirtAddr(env[i] as u64)) - .unwrap() - .as_usize(), - )); - } - env.push(ptr::null::()); - - // ask uhyve for the environment - let mut syscmdval = SysCmdval::new( - VirtAddr(argv_phy.as_ptr() as u64), - VirtAddr(env_phy.as_ptr() as u64), - ); - uhyve_send(UHYVE_PORT_CMDVAL, &mut syscmdval); - - let argv = argv.leak().as_ptr(); - let env = env.leak().as_ptr(); - (syscmdsize.argc, argv, env) - } - fn shutdown(&self, error_code: i32) -> ! { let mut sysexit = SysExit::new(error_code); uhyve_send(UHYVE_PORT_EXIT, &mut sysexit);