diff --git a/kernel/arch/hosted/src/lib.rs b/kernel/arch/hosted/src/lib.rs index a9a68b20..7a0024e5 100644 --- a/kernel/arch/hosted/src/lib.rs +++ b/kernel/arch/hosted/src/lib.rs @@ -78,6 +78,10 @@ impl Architecture for ArchitectureImpl { fn wait_for_interrupt() { unimplemented!() } + + fn halt() -> ! { + unimplemented!() + } } impl KernelTableManager for KernelTableManagerImpl { diff --git a/kernel/libk/src/vfs/file/mod.rs b/kernel/libk/src/vfs/file/mod.rs index 4de50bce..dd966258 100644 --- a/kernel/libk/src/vfs/file/mod.rs +++ b/kernel/libk/src/vfs/file/mod.rs @@ -621,6 +621,7 @@ mod tests { }; use std::sync::{Arc, Mutex}; + use async_trait::async_trait; use yggdrasil_abi::{ error::Error, io::{DirectoryEntry, FileType, OpenOptions, SeekFrom}, @@ -859,49 +860,4 @@ mod tests { assert_eq!(file.tell().unwrap(), 9); assert_eq!(&buf[..7], b"l123456"); } - - #[test] - fn char_device() { - struct C; - - impl FileReadiness for C { - fn poll_read(&self, _cx: &mut Context<'_>) -> Poll> { - unreachable!() - } - } - - impl CharDevice for C { - fn read(&self, buf: &mut [u8]) -> Result { - buf.fill(b'@'); - Ok(buf.len()) - } - - fn is_writable(&self) -> bool { - false - } - } - - static DEV: C = C; - - let node = Node::char(&DEV, NodeFlags::empty()); - let mut buf = [0; 512]; - - let err = node - .open(OpenOptions::WRITE, AccessToken::test_authorized()) - .unwrap_err(); - assert_eq!(err, Error::ReadOnly); - - let file = node - .open(OpenOptions::READ, AccessToken::test_authorized()) - .unwrap(); - assert_eq!(file.tell().unwrap_err(), Error::InvalidOperation); - assert_eq!( - file.seek(SeekFrom::Start(10)).unwrap_err(), - Error::InvalidOperation - ); - assert_eq!(file.read(&mut buf).unwrap(), 512); - assert_eq!(buf, [b'@'; 512]); - - assert_eq!(file.write(b"1234").unwrap_err(), Error::ReadOnly); - } } diff --git a/kernel/libk/src/vfs/ioctx.rs b/kernel/libk/src/vfs/ioctx.rs index a6d2d54b..62a30fba 100644 --- a/kernel/libk/src/vfs/ioctx.rs +++ b/kernel/libk/src/vfs/ioctx.rs @@ -566,7 +566,7 @@ mod tests { let l1 = fixed_symlink(f1.clone()); let root = mdir([("l1", l1.clone())]); - let mut ioctx = IoContext::new(root.clone()); + let ioctx = IoContext::new(root.clone()); // No follow let node = ioctx.find(None, "/l1", false, true).unwrap(); @@ -626,7 +626,7 @@ mod tests { let root_d1 = mdir([("f1", root_d1_f1.clone())]); let root = mdir([("f1", root_f1.clone()), ("d1", root_d1.clone())]); - let mut ioctx = IoContext::new(root.clone()); + let ioctx = IoContext::new(root.clone()); // Ok paths let node = ioctx.find(None, Path::empty(), false, false).unwrap(); diff --git a/kernel/src/syscall/imp/sys_io.rs b/kernel/src/syscall/imp/sys_io.rs index 2ef45543..860d05a0 100644 --- a/kernel/src/syscall/imp/sys_io.rs +++ b/kernel/src/syscall/imp/sys_io.rs @@ -75,11 +75,14 @@ pub(crate) fn read(fd: RawFd, buffer: &mut [u8]) -> Result { run_with_io(&process, |io| io.files.file(fd)?.read(buffer)) } -pub(crate) fn seek(fd: RawFd, pos: SeekFrom) -> Result { +pub(crate) fn seek(fd: RawFd, pos: SeekFrom, output: &mut u64) -> Result<(), Error> { let thread = Thread::current(); let process = thread.process(); - run_with_io(&process, |io| io.files.file(fd)?.seek(pos)) + run_with_io(&process, |io| { + *output = io.files.file(fd)?.seek(pos)?; + Ok(()) + }) } pub(crate) fn open_directory(at: Option, path: &str) -> Result { diff --git a/lib/abi-lib/Cargo.toml b/lib/abi-lib/Cargo.toml index 4845c848..0eb3c554 100644 --- a/lib/abi-lib/Cargo.toml +++ b/lib/abi-lib/Cargo.toml @@ -13,3 +13,6 @@ rustc-dep-of-std = [ "core", "compiler_builtins/rustc-dep-of-std", ] + +[lints.rust] +unexpected_cfgs = { level = "allow", check-cfg = ['cfg(rust_analyzer)'] } diff --git a/lib/abi-lib/src/primitive_impls.rs b/lib/abi-lib/src/primitive_impls.rs index ad486713..f2262d31 100644 --- a/lib/abi-lib/src/primitive_impls.rs +++ b/lib/abi-lib/src/primitive_impls.rs @@ -20,8 +20,41 @@ macro_rules! numeric_impl { }; } -numeric_impl!(u8, u16, u32, u64); -numeric_impl!(i8, i16, i32, i64); +numeric_impl!(u8, u16, u32); +numeric_impl!(i8, i16, i32); + +#[cfg(any(target_pointer_width = "64", rust_analyzer))] +numeric_impl!(u64, i64); + +#[cfg(any(target_pointer_width = "32", rust_analyzer))] +impl crate::SyscallFatRegister for u64 { + fn as_syscall_meta(&self) -> usize { + todo!() + } + + fn as_syscall_data(&self) -> usize { + todo!() + } + + fn from_syscall_registers(_meta: usize, _data: usize) -> Self { + todo!() + } +} + +#[cfg(any(target_pointer_width = "32", rust_analyzer))] +impl crate::SyscallFatRegister for u32 { + fn as_syscall_meta(&self) -> usize { + todo!() + } + + fn as_syscall_data(&self) -> usize { + todo!() + } + + fn from_syscall_registers(_meta: usize, _data: usize) -> Self { + todo!() + } +} unsafe impl ThinWrapped for () {} diff --git a/lib/abi/def/yggdrasil.abi b/lib/abi/def/yggdrasil.abi index 7cb06a48..e9576186 100644 --- a/lib/abi/def/yggdrasil.abi +++ b/lib/abi/def/yggdrasil.abi @@ -83,7 +83,7 @@ syscall open(at: Option, path: &str, opts: OpenOptions, mode: FileMode) - syscall close(fd: RawFd) -> Result<()>; syscall write(fd: RawFd, data: &[u8]) -> Result; syscall read(fd: RawFd, data: &mut [u8]) -> Result; -syscall seek(fd: RawFd, pos: SeekFrom) -> Result; +syscall seek(fd: RawFd, pos: SeekFrom, output: &mut u64) -> Result<()>; syscall open_directory(at: Option, path: &str) -> Result; syscall read_directory_entries(fd: RawFd, entries: &mut [MaybeUninit]) -> Result; diff --git a/tool/abi-generator/src/abi/mod.rs b/tool/abi-generator/src/abi/mod.rs index 84f06cf9..978d9862 100644 --- a/tool/abi-generator/src/abi/mod.rs +++ b/tool/abi-generator/src/abi/mod.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, path::Path, rc::Rc}; use proc_macro2::{Span, TokenStream}; use quote::{quote, TokenStreamExt}; -use syn::{punctuated::Punctuated, spanned::Spanned, token, Ident, Token}; +use syn::{punctuated::Punctuated, spanned::Spanned, token, Token}; pub mod ty; @@ -367,15 +367,11 @@ impl GenerateTypeDefinition for EnumType { fn generate_transparent_struct( attributes: &Attributes, name: &syn::Ident, - repr: &TypeRepr, - is_thin: bool, + env: &TargetEnv, + abi_type: AbiPrimitive, ) -> TokenStream { - let TypeRepr(repr) = &repr; - let real_repr = match repr.to_string().as_str() { - "u31" => Ident::new("u32", repr.span()), - "u63" => Ident::new("u64", repr.span()), - _ => repr.clone(), - }; + let is_thin = abi_type.width(env) <= env.thin_pointer_width; + let real_repr = abi_type.as_rust_type(); let attributes = attributes.filtered(|attr| !attr.path().is_ident("default")); @@ -433,17 +429,11 @@ fn generate_transparent_struct( impl GenerateTypeDefinition for NewType { fn generate_type_definition(&self, abi_type: &ComplexType, env: &TargetEnv) -> TokenStream { let Self { - attributes, - name, - repr, + attributes, name, .. } = self; + let abi_type = abi_type.as_primitive().unwrap(); - generate_transparent_struct( - attributes, - name, - repr, - abi_type.width(env) < env.fat_pointer_width, - ) + generate_transparent_struct(attributes, name, env, abi_type) } } @@ -452,21 +442,17 @@ impl GenerateTypeDefinition for BitfieldType { let Self { attributes, name, - repr, fields, + .. } = self; + let abi_type = abi_type.as_primitive().unwrap(); // Find default attribute, if any let default_attr: Option> = attributes .iter() .find_map(|attr| attr.path().is_ident("default").then_some(attr.parse_args())); - let base = generate_transparent_struct( - attributes, - name, - repr, - abi_type.width(env) < env.fat_pointer_width, - ); + let base = generate_transparent_struct(attributes, name, env, abi_type); let mut field_impls = TokenStream::new(); for BitfieldTypeField { diff --git a/tool/abi-generator/src/abi/ty/complex.rs b/tool/abi-generator/src/abi/ty/complex.rs index 65871692..05a8d293 100644 --- a/tool/abi-generator/src/abi/ty/complex.rs +++ b/tool/abi-generator/src/abi/ty/complex.rs @@ -46,6 +46,8 @@ impl ComplexType { pub fn as_primitive(&self) -> Option { if let Self::Simple(SimpleType::Primitive(ty)) = self { Some(*ty) + } else if let Self::Simple(SimpleType::Transparent { inner, .. }) = self { + Some(*inner) } else { None } @@ -56,14 +58,17 @@ impl Type for ComplexType { fn width(&self, env: &TargetEnv) -> TypeWidth { match self { Self::Simple(ty) => ty.width(env), - Self::Option(ty) | Self::Result(ty) => match ty.kind() { - TypeKind::Other => ty.width(env).double(), + Self::Option(ty) | Self::Result(ty) => match (ty.kind(), ty.width(env)) { + // Some(val) -> val + // None -> usize::MAX + (_, TypeWidth::U31) => TypeWidth::U32, + (TypeKind::Other, _) => ty.width(env).double(), // Some(&[1, 2, 3]) -> (ptr, len), where ptr and len are non-zero // None -> (null, 0) - TypeKind::FatPointer => env.fat_pointer_width, + (TypeKind::FatPointer, _) => env.fat_pointer_width, // Some(&x) -> ptr, where ptr is non-zero // None -> null - TypeKind::ThinPointer => env.thin_pointer_width, + (TypeKind::ThinPointer, _) => env.thin_pointer_width, }, Self::Tuple(_) => TypeWidth::Unknown, Self::Extern { .. } => TypeWidth::Unknown, diff --git a/tool/abi-generator/src/abi/ty/mod.rs b/tool/abi-generator/src/abi/ty/mod.rs index d07646a9..ca78c082 100644 --- a/tool/abi-generator/src/abi/ty/mod.rs +++ b/tool/abi-generator/src/abi/ty/mod.rs @@ -100,6 +100,10 @@ mod tests { thin_pointer_width: TypeWidth::U64, fat_pointer_width: TypeWidth::U128, }; + const TARGET_32: TargetEnv = TargetEnv { + thin_pointer_width: TypeWidth::U32, + fat_pointer_width: TypeWidth::U64, + }; #[test] fn type_width() { @@ -152,6 +156,30 @@ mod tests { assert_eq!(quote!(&[u8]).to_string(), ty.as_rust_type().to_string()); } + #[test] + fn u31_type() { + let ty = SimpleType::Primitive(AbiPrimitive::U31); + let option_ty = ComplexType::Option(Rc::new(ComplexType::Simple(ty.clone()))); + + assert_eq!(ty.width(&TARGET_32), TypeWidth::U31); + assert_eq!(ty.width(&TARGET_64), TypeWidth::U31); + assert_eq!(ty.width(&TARGET_32).double(), TypeWidth::U64); + assert_eq!(ty.width(&TARGET_64).double(), TypeWidth::U64); + + assert_eq!(option_ty.width(&TARGET_32), TypeWidth::U32); + assert_eq!(option_ty.width(&TARGET_64), TypeWidth::U32); + + let val = Ident::new("val0", Span::call_site()); + assert_eq!( + ty.emit_to_syscall_arguments(&TARGET_64, &val).to_string(), + quote!(val0 as usize).to_string() + ); + assert_eq!( + ty.emit_to_syscall_arguments(&TARGET_32, &val).to_string(), + quote!(val0 as usize).to_string() + ); + } + #[test] fn emit_to_syscall_arguments() { let ty = SimpleType::Reference { @@ -160,10 +188,31 @@ mod tests { AbiPrimitive::U64, ))), }; + let val = Ident::new("val0", Span::call_site()); assert_eq!( ty.emit_to_syscall_arguments(&TARGET_64, &val).to_string(), - quote!((val0 as *const _).expose_addr()).to_string() + quote!((val0 as *const u64).addr()).to_string() + ); + + let val = Ident::new("val0", Span::call_site()); + assert_eq!( + ty.emit_to_syscall_arguments(&TARGET_32, &val).to_string(), + quote!((val0 as *const u64).addr()).to_string() + ); + + let ty = SimpleType::Primitive(AbiPrimitive::U64); + + let val = Ident::new("val0", Span::call_site()); + assert_eq!( + ty.emit_to_syscall_arguments(&TARGET_64, &val).to_string(), + quote!(val0 as usize).to_string() + ); + + let val = Ident::new("val0", Span::call_site()); + assert_eq!( + ty.emit_to_syscall_arguments(&TARGET_32, &val).to_string(), + quote!(val0 as usize, (val0 >> 32) as usize).to_string() ); } } diff --git a/tool/abi-generator/src/abi/ty/primitive.rs b/tool/abi-generator/src/abi/ty/primitive.rs index eb92be9a..a6fd6b87 100644 --- a/tool/abi-generator/src/abi/ty/primitive.rs +++ b/tool/abi-generator/src/abi/ty/primitive.rs @@ -60,7 +60,7 @@ impl Type for AbiPrimitive { Self::USize => quote!(usize), Self::Bool => quote!(bool), - Self::U31 => todo!(), + Self::U31 => quote!(u32), } } @@ -68,7 +68,9 @@ impl Type for AbiPrimitive { match self { Self::USize => quote!(#value), Self::U128 => todo!("Emit to syscall for u128"), - Self::U64 if env.thin_pointer_width == TypeWidth::U32 => todo!(), + Self::U64 if env.thin_pointer_width == TypeWidth::U32 => { + quote!(#value as usize, (#value >> 32) as usize) + } _ => quote!(#value as usize), } } @@ -82,7 +84,9 @@ impl Type for AbiPrimitive { match self { Self::Bool => (quote!(#args[#index] != 0), 1), Self::U128 => todo!("Emit from syscall for u128"), - Self::U64 if env.thin_pointer_width == TypeWidth::U32 => todo!(), + Self::U64 if env.thin_pointer_width == TypeWidth::U32 => { + todo!(); + } _ => { let ty = self.as_rust_type(); (quote!(#args[#index] as #ty), 1) diff --git a/xtask/src/build/mod.rs b/xtask/src/build/mod.rs index 03911b8a..d1748486 100644 --- a/xtask/src/build/mod.rs +++ b/xtask/src/build/mod.rs @@ -129,8 +129,10 @@ pub fn test_all(env: BuildEnv) -> Result<(), Error> { "kernel/driver/fs/memfs", "lib/abi", "kernel/libk", - "kernel/libk-util", + "kernel/libk/libk-util", + "tool/abi-generator", ] { + log::info!("Run tests: {:?}", path); CargoBuilder::Host(env.verbose).run(env.workspace_root.join(path), "test")?; } Ok(())